• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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