xref: /aosp_15_r20/external/antlr/runtime/ObjC/Framework/LinkedHashMap.h (revision 16467b971bd3e2009fad32dd79016f2c7e421deb)
1*16467b97STreehugger Robot #import "HashMap.h"
2*16467b97STreehugger Robot /**
3*16467b97STreehugger Robot  * <p>Hash table and linked list implementation of the <tt>Map</tt> interface,
4*16467b97STreehugger Robot  * with predictable iteration order.  This implementation differs from
5*16467b97STreehugger Robot  * <tt>HashMap</tt> in that it maintains a doubly-linked list running through
6*16467b97STreehugger Robot  * all of its entries.  This linked list defines the iteration ordering,
7*16467b97STreehugger Robot  * which is normally the order in which keys were inserted into the map
8*16467b97STreehugger Robot  * (<i>insertion-order</i>).  Note that insertion order is not affected
9*16467b97STreehugger Robot  * if a key is <i>re-inserted</i> into the map.  (A key <tt>k</tt> is
10*16467b97STreehugger Robot  * reinserted into a map <tt>m</tt> if <tt>m.put(k, v)</tt> is invoked when
11*16467b97STreehugger Robot  * <tt>m.containsKey(k)</tt> would return <tt>true</tt> immediately prior to
12*16467b97STreehugger Robot  * the invocation.)
13*16467b97STreehugger Robot  *
14*16467b97STreehugger Robot  * <p>This implementation spares its clients from the unspecified, generally
15*16467b97STreehugger Robot  * chaotic ordering provided by {@link HashMap} (and {@link Hashtable}),
16*16467b97STreehugger Robot  * without incurring the increased cost associated with {@link TreeMap}.  It
17*16467b97STreehugger Robot  * can be used to produce a copy of a map that has the same order as the
18*16467b97STreehugger Robot  * original, regardless of the original map's implementation:
19*16467b97STreehugger Robot  * <pre>
20*16467b97STreehugger Robot  * void foo(Map m) {
21*16467b97STreehugger Robot  * Map copy = new LinkedHashMap(m);
22*16467b97STreehugger Robot  * ...
23*16467b97STreehugger Robot  * }
24*16467b97STreehugger Robot  * </pre>
25*16467b97STreehugger Robot  * This technique is particularly useful if a module takes a map on input,
26*16467b97STreehugger Robot  * copies it, and later returns results whose order is determined by that of
27*16467b97STreehugger Robot  * the copy.  (Clients generally appreciate having things returned in the same
28*16467b97STreehugger Robot  * order they were presented.)
29*16467b97STreehugger Robot  *
30*16467b97STreehugger Robot  * <p>A special {@link #LinkedHashMap(NSInteger,float,boolean) constructor} is
31*16467b97STreehugger Robot  * provided to create a linked hash map whose order of iteration is the order
32*16467b97STreehugger Robot  * in which its entries were last accessed, from least-recently accessed to
33*16467b97STreehugger Robot  * most-recently (<i>access-order</i>).  This kind of map is well-suited to
34*16467b97STreehugger Robot  * building LRU caches.  Invoking the <tt>put</tt> or <tt>get</tt> method
35*16467b97STreehugger Robot  * results in an access to the corresponding entry (assuming it exists after
36*16467b97STreehugger Robot  * the invocation completes).  The <tt>putAll</tt> method generates one entry
37*16467b97STreehugger Robot  * access for each mapping in the specified map, in the order that key-value
38*16467b97STreehugger Robot  * mappings are provided by the specified map's entry set iterator.  <i>No
39*16467b97STreehugger Robot  * other methods generate entry accesses.</i> In particular, operations on
40*16467b97STreehugger Robot  * collection-views do <i>not</i> affect the order of iteration of the backing
41*16467b97STreehugger Robot  * map.
42*16467b97STreehugger Robot  *
43*16467b97STreehugger Robot  * <p>The {@link #removeEldestEntry(Map.Entry)} method may be overridden to
44*16467b97STreehugger Robot  * impose a policy for removing stale mappings automatically when new mappings
45*16467b97STreehugger Robot  * are added to the map.
46*16467b97STreehugger Robot  *
47*16467b97STreehugger Robot  * <p>This class provides all of the optional <tt>Map</tt> operations, and
48*16467b97STreehugger Robot  * permits null elements.  Like <tt>HashMap</tt>, it provides constant-time
49*16467b97STreehugger Robot  * performance for the basic operations (<tt>add</tt>, <tt>contains</tt> and
50*16467b97STreehugger Robot  * <tt>remove</tt>), assuming the hash function disperses elements
51*16467b97STreehugger Robot  * properly among the buckets.  Performance is likely to be just slightly
52*16467b97STreehugger Robot  * below that of <tt>HashMap</tt>, due to the added expense of maintaining the
53*16467b97STreehugger Robot  * linked list, with one exception: Iteration over the collection-views
54*16467b97STreehugger Robot  * of a <tt>LinkedHashMap</tt> requires time proportional to the <i>size</i>
55*16467b97STreehugger Robot  * of the map, regardless of its capacity.  Iteration over a <tt>HashMap</tt>
56*16467b97STreehugger Robot  * is likely to be more expensive, requiring time proportional to its
57*16467b97STreehugger Robot  * <i>capacity</i>.
58*16467b97STreehugger Robot  *
59*16467b97STreehugger Robot  * <p>A linked hash map has two parameters that affect its performance:
60*16467b97STreehugger Robot  * <i>initial capacity</i> and <i>load factor</i>.  They are defined precisely
61*16467b97STreehugger Robot  * as for <tt>HashMap</tt>.  Note, however, that the penalty for choosing an
62*16467b97STreehugger Robot  * excessively high value for initial capacity is less severe for this class
63*16467b97STreehugger Robot  * than for <tt>HashMap</tt>, as iteration times for this class are unaffected
64*16467b97STreehugger Robot  * by capacity.
65*16467b97STreehugger Robot  *
66*16467b97STreehugger Robot  * <p><strong>Note that this implementation is not synchronized.</strong>
67*16467b97STreehugger Robot  * If multiple threads access a linked hash map concurrently, and at least
68*16467b97STreehugger Robot  * one of the threads modifies the map structurally, it <em>must</em> be
69*16467b97STreehugger Robot  * synchronized externally.  This is typically accomplished by
70*16467b97STreehugger Robot  * synchronizing on some object that naturally encapsulates the map.
71*16467b97STreehugger Robot  *
72*16467b97STreehugger Robot  * If no such object exists, the map should be "wrapped" using the
73*16467b97STreehugger Robot  * {@link Collections#synchronizedMap Collections.synchronizedMap}
74*16467b97STreehugger Robot  * method.  This is best done at creation time, to prevent accidental
75*16467b97STreehugger Robot  * unsynchronized access to the map:<pre>
76*16467b97STreehugger Robot  * Map m = Collections.synchronizedMap(new LinkedHashMap(...));</pre>
77*16467b97STreehugger Robot  *
78*16467b97STreehugger Robot  * A structural modification is any operation that adds or deletes one or more
79*16467b97STreehugger Robot  * mappings or, in the case of access-ordered linked hash maps, affects
80*16467b97STreehugger Robot  * iteration order.  In insertion-ordered linked hash maps, merely changing
81*16467b97STreehugger Robot  * the value associated with a key that is already contained in the map is not
82*16467b97STreehugger Robot  * a structural modification.  <strong>In access-ordered linked hash maps,
83*16467b97STreehugger Robot  * merely querying the map with <tt>get</tt> is a structural
84*16467b97STreehugger Robot  * modification.</strong>)
85*16467b97STreehugger Robot  *
86*16467b97STreehugger Robot  * <p>The iterators returned by the <tt>iterator</tt> method of the collections
87*16467b97STreehugger Robot  * returned by all of this class's collection view methods are
88*16467b97STreehugger Robot  * <em>fail-fast</em>: if the map is structurally modified at any time after
89*16467b97STreehugger Robot  * the iterator is created, in any way except through the iterator's own
90*16467b97STreehugger Robot  * <tt>remove</tt> method, the iterator will throw a {@link
91*16467b97STreehugger Robot  * ConcurrentModificationException}.  Thus, in the face of concurrent
92*16467b97STreehugger Robot  * modification, the iterator fails quickly and cleanly, rather than risking
93*16467b97STreehugger Robot  * arbitrary, non-deterministic behavior at an undetermined time in the future.
94*16467b97STreehugger Robot  *
95*16467b97STreehugger Robot  * <p>Note that the fail-fast behavior of an iterator cannot be guaranteed
96*16467b97STreehugger Robot  * as it is, generally speaking, impossible to make any hard guarantees in the
97*16467b97STreehugger Robot  * presence of unsynchronized concurrent modification.  Fail-fast iterators
98*16467b97STreehugger Robot  * throw <tt>ConcurrentModificationException</tt> on a best-effort basis.
99*16467b97STreehugger Robot  * Therefore, it would be wrong to write a program that depended on this
100*16467b97STreehugger Robot  * exception for its correctness:   <i>the fail-fast behavior of iterators
101*16467b97STreehugger Robot  * should be used only to detect bugs.</i>
102*16467b97STreehugger Robot  *
103*16467b97STreehugger Robot  * <p>This class is a member of the
104*16467b97STreehugger Robot  * <a href="{@docRoot}/../technotes/guides/collections/index.html">
105*16467b97STreehugger Robot  * Java Collections Framework</a>.
106*16467b97STreehugger Robot  *
107*16467b97STreehugger Robot  * @param <K> the type of keys maintained by this map
108*16467b97STreehugger Robot  * @param <V> the type of mapped values
109*16467b97STreehugger Robot  *
110*16467b97STreehugger Robot  * @author  Josh Bloch
111*16467b97STreehugger Robot  * @see     Object#hashCode()
112*16467b97STreehugger Robot  * @see     Collection
113*16467b97STreehugger Robot  * @see     Map
114*16467b97STreehugger Robot  * @see     HashMap
115*16467b97STreehugger Robot  * @see     TreeMap
116*16467b97STreehugger Robot  * @see     Hashtable
117*16467b97STreehugger Robot  * @since   1.4
118*16467b97STreehugger Robot  */
119*16467b97STreehugger Robot @class LinkedHashMap;
120*16467b97STreehugger Robot 
121*16467b97STreehugger Robot /**
122*16467b97STreehugger Robot  * LinkedHashMap entry.
123*16467b97STreehugger Robot  */
124*16467b97STreehugger Robot 
125*16467b97STreehugger Robot @interface LHMEntry : HMEntry
126*16467b97STreehugger Robot {
127*16467b97STreehugger Robot     LHMEntry *before;
128*16467b97STreehugger Robot     LHMEntry *after;
129*16467b97STreehugger Robot     BOOL accessOrder;
130*16467b97STreehugger Robot }
131*16467b97STreehugger Robot 
132*16467b97STreehugger Robot @property (retain) LHMEntry *before;
133*16467b97STreehugger Robot @property (retain) LHMEntry *after;
134*16467b97STreehugger Robot @property (assign) BOOL accessOrder;
135*16467b97STreehugger Robot 
136*16467b97STreehugger Robot - (id) newEntry:(NSInteger)aHash key:(NSString *)aKey value:(id)aValue next:(LHMEntry *)aNext;
137*16467b97STreehugger Robot 
138*16467b97STreehugger Robot - (id) init:(NSInteger)hash key:(NSString *)key value:(id)value next:(LHMEntry *)next;
139*16467b97STreehugger Robot - (void) recordAccess:(LinkedHashMap *)m;
140*16467b97STreehugger Robot - (void) recordRemoval:(LinkedHashMap *)m;
141*16467b97STreehugger Robot 
142*16467b97STreehugger Robot @end
143*16467b97STreehugger Robot 
144*16467b97STreehugger Robot /**
145*16467b97STreehugger Robot  * LinkedHashMapIterator.
146*16467b97STreehugger Robot  */
147*16467b97STreehugger Robot 
148*16467b97STreehugger Robot @interface LinkedHashIterator : HashIterator
149*16467b97STreehugger Robot {
150*16467b97STreehugger Robot     LHMEntry *nextEntry;
151*16467b97STreehugger Robot     LHMEntry *lastReturned;
152*16467b97STreehugger Robot     LinkedHashMap *lhm;
153*16467b97STreehugger Robot }
154*16467b97STreehugger Robot 
155*16467b97STreehugger Robot @property (retain) LHMEntry *nextEntry;
156*16467b97STreehugger Robot @property (retain) LHMEntry *lastReturned;
157*16467b97STreehugger Robot @property (retain) LinkedHashMap *lhm;
158*16467b97STreehugger Robot 
159*16467b97STreehugger Robot + (LinkedHashIterator *) newIterator:(LinkedHashMap *)aLHM;
160*16467b97STreehugger Robot 
161*16467b97STreehugger Robot - (id) init:(LinkedHashMap *)aLHM;
162*16467b97STreehugger Robot - (BOOL) hasNext;
163*16467b97STreehugger Robot - (void) remove;
164*16467b97STreehugger Robot - (LHMEntry *) nextEntry;
165*16467b97STreehugger Robot @end
166*16467b97STreehugger Robot 
167*16467b97STreehugger Robot @interface LHMEntryIterator : LinkedHashIterator
168*16467b97STreehugger Robot {
169*16467b97STreehugger Robot }
170*16467b97STreehugger Robot 
171*16467b97STreehugger Robot + (LHMEntryIterator *)newIterator:(LinkedHashMap *)aHM;
172*16467b97STreehugger Robot 
173*16467b97STreehugger Robot - (id) init:(LinkedHashMap *)aHM;
174*16467b97STreehugger Robot - (LHMEntry *) next;
175*16467b97STreehugger Robot @end
176*16467b97STreehugger Robot 
177*16467b97STreehugger Robot @interface LHMKeyIterator : LinkedHashIterator
178*16467b97STreehugger Robot {
179*16467b97STreehugger Robot }
180*16467b97STreehugger Robot 
181*16467b97STreehugger Robot + (LHMKeyIterator *)newIterator:(LinkedHashMap *)aHM;
182*16467b97STreehugger Robot 
183*16467b97STreehugger Robot - (id) init:(LinkedHashMap *)aHM;
184*16467b97STreehugger Robot - (NSString *) next;
185*16467b97STreehugger Robot @end
186*16467b97STreehugger Robot 
187*16467b97STreehugger Robot @interface LHMValueIterator : LinkedHashIterator
188*16467b97STreehugger Robot {
189*16467b97STreehugger Robot }
190*16467b97STreehugger Robot 
191*16467b97STreehugger Robot + (LHMValueIterator *)newIterator:(LinkedHashMap *)aHM;
192*16467b97STreehugger Robot 
193*16467b97STreehugger Robot - (id) init:(LinkedHashMap *)aHM;
194*16467b97STreehugger Robot - (id) next;
195*16467b97STreehugger Robot @end
196*16467b97STreehugger Robot 
197*16467b97STreehugger Robot 
198*16467b97STreehugger Robot @interface LinkedHashMap : HashMap
199*16467b97STreehugger Robot {
200*16467b97STreehugger Robot 
201*16467b97STreehugger Robot     /**
202*16467b97STreehugger Robot      * The head of the doubly linked list.
203*16467b97STreehugger Robot      */
204*16467b97STreehugger Robot     LHMEntry *header;
205*16467b97STreehugger Robot     /**
206*16467b97STreehugger Robot      * The iteration ordering method for this linked hash map: <tt>true</tt>
207*16467b97STreehugger Robot      * for access-order, <tt>false</tt> for insertion-order.
208*16467b97STreehugger Robot      *
209*16467b97STreehugger Robot      * @serial
210*16467b97STreehugger Robot      */
211*16467b97STreehugger Robot     BOOL accessOrder;
212*16467b97STreehugger Robot 
213*16467b97STreehugger Robot }
214*16467b97STreehugger Robot 
215*16467b97STreehugger Robot @property (retain) LHMEntry *header;
216*16467b97STreehugger Robot @property (assign) BOOL accessOrder;
217*16467b97STreehugger Robot 
218*16467b97STreehugger Robot + (id) newLinkedHashMap:(NSInteger)anInitialCapacity;
219*16467b97STreehugger Robot + (id) newLinkedHashMap:(NSInteger)anInitialCapacity
220*16467b97STreehugger Robot              loadFactor:(float)loadFactor;
221*16467b97STreehugger Robot + (id) newLinkedHashMap:(NSInteger)anInitialCapacity
222*16467b97STreehugger Robot              loadFactor:(float)loadFactor
223*16467b97STreehugger Robot             accessOrder:(BOOL)anAccessOrder;
224*16467b97STreehugger Robot 
225*16467b97STreehugger Robot - (id) init:(NSInteger)initialCapacity loadFactor:(float)loadFactor accessOrder:(BOOL)accessOrder;
226*16467b97STreehugger Robot - (id) init:(NSInteger)initialCapacity loadFactor:(float)loadFactor;
227*16467b97STreehugger Robot - (id) init:(NSInteger)initialCapacity;
228*16467b97STreehugger Robot - (id) init;
229*16467b97STreehugger Robot - (id) initWithM:(AMutableDictionary *)m;
230*16467b97STreehugger Robot - (void) transfer:(NSArray *)newTable;
231*16467b97STreehugger Robot - (BOOL) containsValue:(NSObject *)value;
232*16467b97STreehugger Robot - (id) get:(NSString *)key;
233*16467b97STreehugger Robot - (void) clear;
234*16467b97STreehugger Robot - (LHMEntryIterator *) newEntryIterator;
235*16467b97STreehugger Robot - (LHMKeyIterator *) newKeyIterator;
236*16467b97STreehugger Robot - (LHMValueIterator *) newValueIterator;
237*16467b97STreehugger Robot - (void) addEntry:(NSInteger)hash key:(NSString *)key value:(id)value bucketIndex:(NSInteger)bucketIndex;
238*16467b97STreehugger Robot - (void) createEntry:(NSInteger)hash key:(NSString *)key value:(id)value bucketIndex:(NSInteger)bucketIndex;
239*16467b97STreehugger Robot - (BOOL) removeEldestEntry:(LHMEntry *)eldest;
240*16467b97STreehugger Robot @end
241