110353ed766fc48a0af6bd33d934439e695c03e3Mahmood Alipackage annotations.util.coll; 210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali 3a74f2668d253bb9375805db0f23a01e30ddfba8fwdietlimport java.util.*; 4a74f2668d253bb9375805db0f23a01e30ddfba8fwdietl 5a74f2668d253bb9375805db0f23a01e30ddfba8fwdietl/*>>> 643367280222c6f50f8085ae8d12a985c257b3ea0Michael Ernstimport org.checkerframework.checker.nullness.qual.*; 7a74f2668d253bb9375805db0f23a01e30ddfba8fwdietl*/ 810353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali 910353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali/** 1010353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali * A simple implementation of {@link KeyedSet} backed by an insertion-order 1110353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali * {@link java.util.LinkedHashMap} and its 1210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali * {@link java.util.LinkedHashMap#values() value collection}. 1310353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali */ 1410353ed766fc48a0af6bd33d934439e695c03e3Mahmood Alipublic class LinkedHashKeyedSet<K, V> extends AbstractSet<V> implements KeyedSet<K, V> { 1510353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali private final Keyer<? extends K, ? super V> keyer; 1610353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali 1710353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali private final Map<K, V> theMap = new LinkedHashMap<K, V>(); 1810353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali 1910353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali final Collection<V> theValues = theMap.values(); 2010353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali 2110353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali /** 2210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali * Constructs a {@link LinkedHashKeyedSet} that uses the given 2310353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali * {@link Keyer} to obtain keys for elements. 2410353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali */ 2510353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali public LinkedHashKeyedSet(Keyer<? extends K, ? super V> keyer) { 2610353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali this.keyer = keyer; 2710353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali } 2810353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali 2910353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali /** 3010353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali * {@inheritDoc} 3110353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali */ 3210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali @Override 3310353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali public int size() { 3410353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali return theValues.size(); 3510353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali } 3610353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali 3710353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali /** 3810353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali * {@inheritDoc} 3910353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali */ 4010353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali @Override 413aff85d01d84fa9d8551ca791036a733ae4a4f39Michael Ernst public boolean contains(Object o) { 4210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali return theValues.contains(o); 4310353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali } 4410353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali 4510353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali private class KeyedSetIterator implements Iterator<V> { 46a74f2668d253bb9375805db0f23a01e30ddfba8fwdietl private final Iterator<V> itr = theValues.iterator(); 4710353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali 48a74f2668d253bb9375805db0f23a01e30ddfba8fwdietl @Override 493aff85d01d84fa9d8551ca791036a733ae4a4f39Michael Ernst public boolean hasNext() { 5010353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali return itr.hasNext(); 5110353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali } 5210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali 53a74f2668d253bb9375805db0f23a01e30ddfba8fwdietl @Override 543aff85d01d84fa9d8551ca791036a733ae4a4f39Michael Ernst public V next() { 5510353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali return itr.next(); 5610353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali } 5710353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali 58a74f2668d253bb9375805db0f23a01e30ddfba8fwdietl @Override 5910353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali public void remove() { 6010353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali itr.remove(); 6110353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali } 6210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali 6310353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali KeyedSetIterator() { 6410353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali } 6510353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali } 6610353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali 6710353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali /** 6810353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali * {@inheritDoc} 6910353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali */ 7010353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali @Override 713aff85d01d84fa9d8551ca791036a733ae4a4f39Michael Ernst public Iterator<V> iterator() { 7210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali return new KeyedSetIterator(); 7310353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali } 7410353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali 7510353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali /** 7610353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali * {@inheritDoc} 7710353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali */ 7810353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali @Override 793aff85d01d84fa9d8551ca791036a733ae4a4f39Michael Ernst public Object[] toArray() { 8010353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali return theValues.toArray(); 8110353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali } 8210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali 8310353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali /** 8410353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali * {@inheritDoc} 8510353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali */ 8610353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali @Override 873aff85d01d84fa9d8551ca791036a733ae4a4f39Michael Ernst public <T> T[] toArray(T[] a) { 8810353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali return theValues.toArray(a); 8910353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali } 9010353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali 9110353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali private boolean checkAdd(int behavior, V old) { 9210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali switch (behavior) { 9310353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali case REPLACE: 9410353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali remove(old); 9510353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali return true; 9610353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali case IGNORE: 9710353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali return false; 9810353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali case THROW_EXCEPTION: 9910353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali throw new IllegalStateException(); 10010353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali default: 10110353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali throw new IllegalArgumentException(); 10210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali } 10310353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali } 10410353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali 1053aff85d01d84fa9d8551ca791036a733ae4a4f39Michael Ernst private static boolean eq(Object x, Object y) { 10610353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali return x == y || (x != null && x.equals(y)); 10710353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali } 10810353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali 10910353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali /** 11010353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali * {@inheritDoc} 11110353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali */ 112a74f2668d253bb9375805db0f23a01e30ddfba8fwdietl @Override 11310353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali public V add(V o, int conflictBehavior, int equalBehavior) { 11410353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali K key = keyer.getKeyFor(o); 11510353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali V old = theMap.get(key); 11610353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali if (old == null 11710353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali || (eq(o, old) ? checkAdd(equalBehavior, old) : checkAdd( 11810353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali conflictBehavior, old))) 11910353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali theMap.put(key, o); 12010353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali return old; 12110353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali } 12210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali 12310353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali /** 12410353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali * {@inheritDoc} 12510353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali */ 12610353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali @Override 12710353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali public boolean add(V o) { 12810353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali return add(o, THROW_EXCEPTION, IGNORE) == null; 12910353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali } 13010353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali 13110353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali /** 13210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali * {@inheritDoc} 13310353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali */ 13410353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali @Override 1353aff85d01d84fa9d8551ca791036a733ae4a4f39Michael Ernst public boolean remove(Object o) { 13610353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali return theValues.remove(o); 13710353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali } 13810353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali 13910353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali /** 14010353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali * {@inheritDoc} 14110353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali */ 14210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali @Override 14310353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali public boolean addAll(Collection<? extends V> c) { 14410353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali boolean changed = false; 145f363307b8c8b78b369f6770b2d0b95eccf6754c9Michael Ernst for (V o : c) { 14610353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali changed |= add(o); 147f363307b8c8b78b369f6770b2d0b95eccf6754c9Michael Ernst } 14810353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali return changed; 14910353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali } 15010353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali 15110353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali /** 15210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali * {@inheritDoc} 15310353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali */ 15410353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali @Override 15510353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali public void clear() { 15610353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali theValues.clear(); 15710353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali } 15810353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali 15910353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali /** 16010353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali * {@inheritDoc} 16110353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali */ 162a74f2668d253bb9375805db0f23a01e30ddfba8fwdietl @Override 1633aff85d01d84fa9d8551ca791036a733ae4a4f39Michael Ernst public Keyer<? extends K, ? super V> getKeyer() { 16410353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali return keyer; 16510353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali } 16610353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali 16710353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali /** 16810353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali * {@inheritDoc} 16910353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali */ 170a74f2668d253bb9375805db0f23a01e30ddfba8fwdietl @Override 17110353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali public V replace(V v) { 17210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali return theMap.put(keyer.getKeyFor(v), v); 17310353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali } 17410353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali 17510353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali /** 17610353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali * {@inheritDoc} 17710353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali */ 178a74f2668d253bb9375805db0f23a01e30ddfba8fwdietl @Override 17910353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali public V lookup(K k) { 18010353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali return theMap.get(k); 18110353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali } 18210353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali 18310353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali // Use inherited equals and hashCode algorithms because 18410353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali // those of HashMap.Values are broken! 18510353ed766fc48a0af6bd33d934439e695c03e3Mahmood Ali} 186