1 package annotations.util.coll; 2 3 import java.util.*; 4 5 /*>>> 6 import org.checkerframework.checker.nullness.qual.*; 7 */ 8 9 /** 10 * A simple implementation of {@link KeyedSet} backed by an insertion-order 11 * {@link java.util.LinkedHashMap} and its 12 * {@link java.util.LinkedHashMap#values() value collection}. 13 */ 14 public class LinkedHashKeyedSet<K, V> extends AbstractSet<V> implements KeyedSet<K, V> { 15 private final Keyer<? extends K, ? super V> keyer; 16 17 private final Map<K, V> theMap = new LinkedHashMap<K, V>(); 18 19 final Collection<V> theValues = theMap.values(); 20 21 /** 22 * Constructs a {@link LinkedHashKeyedSet} that uses the given 23 * {@link Keyer} to obtain keys for elements. 24 */ LinkedHashKeyedSet(Keyer<? extends K, ? super V> keyer)25 public LinkedHashKeyedSet(Keyer<? extends K, ? super V> keyer) { 26 this.keyer = keyer; 27 } 28 29 /** 30 * {@inheritDoc} 31 */ 32 @Override size()33 public int size() { 34 return theValues.size(); 35 } 36 37 /** 38 * {@inheritDoc} 39 */ 40 @Override contains(Object o)41 public boolean contains(Object o) { 42 return theValues.contains(o); 43 } 44 45 private class KeyedSetIterator implements Iterator<V> { 46 private final Iterator<V> itr = theValues.iterator(); 47 48 @Override hasNext()49 public boolean hasNext() { 50 return itr.hasNext(); 51 } 52 53 @Override next()54 public V next() { 55 return itr.next(); 56 } 57 58 @Override remove()59 public void remove() { 60 itr.remove(); 61 } 62 KeyedSetIterator()63 KeyedSetIterator() { 64 } 65 } 66 67 /** 68 * {@inheritDoc} 69 */ 70 @Override iterator()71 public Iterator<V> iterator() { 72 return new KeyedSetIterator(); 73 } 74 75 /** 76 * {@inheritDoc} 77 */ 78 @Override toArray()79 public Object[] toArray() { 80 return theValues.toArray(); 81 } 82 83 /** 84 * {@inheritDoc} 85 */ 86 @Override toArray(T[] a)87 public <T> T[] toArray(T[] a) { 88 return theValues.toArray(a); 89 } 90 checkAdd(int behavior, V old)91 private boolean checkAdd(int behavior, V old) { 92 switch (behavior) { 93 case REPLACE: 94 remove(old); 95 return true; 96 case IGNORE: 97 return false; 98 case THROW_EXCEPTION: 99 throw new IllegalStateException(); 100 default: 101 throw new IllegalArgumentException(); 102 } 103 } 104 eq(Object x, Object y)105 private static boolean eq(Object x, Object y) { 106 return x == y || (x != null && x.equals(y)); 107 } 108 109 /** 110 * {@inheritDoc} 111 */ 112 @Override add(V o, int conflictBehavior, int equalBehavior)113 public V add(V o, int conflictBehavior, int equalBehavior) { 114 K key = keyer.getKeyFor(o); 115 V old = theMap.get(key); 116 if (old == null 117 || (eq(o, old) ? checkAdd(equalBehavior, old) : checkAdd( 118 conflictBehavior, old))) 119 theMap.put(key, o); 120 return old; 121 } 122 123 /** 124 * {@inheritDoc} 125 */ 126 @Override add(V o)127 public boolean add(V o) { 128 return add(o, THROW_EXCEPTION, IGNORE) == null; 129 } 130 131 /** 132 * {@inheritDoc} 133 */ 134 @Override remove(Object o)135 public boolean remove(Object o) { 136 return theValues.remove(o); 137 } 138 139 /** 140 * {@inheritDoc} 141 */ 142 @Override addAll(Collection<? extends V> c)143 public boolean addAll(Collection<? extends V> c) { 144 boolean changed = false; 145 for (V o : c) { 146 changed |= add(o); 147 } 148 return changed; 149 } 150 151 /** 152 * {@inheritDoc} 153 */ 154 @Override clear()155 public void clear() { 156 theValues.clear(); 157 } 158 159 /** 160 * {@inheritDoc} 161 */ 162 @Override getKeyer()163 public Keyer<? extends K, ? super V> getKeyer() { 164 return keyer; 165 } 166 167 /** 168 * {@inheritDoc} 169 */ 170 @Override replace(V v)171 public V replace(V v) { 172 return theMap.put(keyer.getKeyFor(v), v); 173 } 174 175 /** 176 * {@inheritDoc} 177 */ 178 @Override lookup(K k)179 public V lookup(K k) { 180 return theMap.get(k); 181 } 182 183 // Use inherited equals and hashCode algorithms because 184 // those of HashMap.Values are broken! 185 } 186