ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/ConcurrentHashMap.java
Revision: 1.45
Committed: Sat Apr 10 14:21:45 2004 UTC (20 years, 1 month ago) by dl
Branch: MAIN
Changes since 1.44: +194 -143 lines
Log Message:
Conform to JSR133:
Declare HashEntry.value field volatile to ensure ordering
Reread value to deal with cases of HashEntry initialization reorderings
Force ordering during rehash by making table field volatile
Eliminate possiblilty of infinite retry in size and containsValue
Minor changes to private method decls  to simplify the above
Make internal docuemntation match code.

File Contents

# User Rev Content
1 dl 1.2 /*
2     * Written by Doug Lea with assistance from members of JCP JSR-166
3 dl 1.36 * Expert Group and released to the public domain, as explained at
4     * http://creativecommons.org/licenses/publicdomain
5 dl 1.2 */
6    
7 tim 1.1 package java.util.concurrent;
8 dl 1.10 import java.util.concurrent.locks.*;
9 tim 1.1 import java.util.*;
10     import java.io.Serializable;
11     import java.io.IOException;
12     import java.io.ObjectInputStream;
13     import java.io.ObjectOutputStream;
14    
15     /**
16 dl 1.4 * A hash table supporting full concurrency of retrievals and
17     * adjustable expected concurrency for updates. This class obeys the
18 dl 1.22 * same functional specification as {@link java.util.Hashtable}, and
19 dl 1.19 * includes versions of methods corresponding to each method of
20 dl 1.25 * <tt>Hashtable</tt>. However, even though all operations are
21 dl 1.19 * thread-safe, retrieval operations do <em>not</em> entail locking,
22     * and there is <em>not</em> any support for locking the entire table
23     * in a way that prevents all access. This class is fully
24     * interoperable with <tt>Hashtable</tt> in programs that rely on its
25 dl 1.4 * thread safety but not on its synchronization details.
26 tim 1.11 *
27 dl 1.25 * <p> Retrieval operations (including <tt>get</tt>) generally do not
28     * block, so may overlap with update operations (including
29     * <tt>put</tt> and <tt>remove</tt>). Retrievals reflect the results
30     * of the most recently <em>completed</em> update operations holding
31     * upon their onset. For aggregate operations such as <tt>putAll</tt>
32     * and <tt>clear</tt>, concurrent retrievals may reflect insertion or
33 dl 1.4 * removal of only some entries. Similarly, Iterators and
34     * Enumerations return elements reflecting the state of the hash table
35     * at some point at or since the creation of the iterator/enumeration.
36 dl 1.25 * They do <em>not</em> throw
37 dl 1.28 * {@link ConcurrentModificationException}. However, iterators are
38 dl 1.25 * designed to be used by only one thread at a time.
39 tim 1.1 *
40 dl 1.19 * <p> The allowed concurrency among update operations is guided by
41     * the optional <tt>concurrencyLevel</tt> constructor argument
42 dl 1.21 * (default 16), which is used as a hint for internal sizing. The
43     * table is internally partitioned to try to permit the indicated
44     * number of concurrent updates without contention. Because placement
45     * in hash tables is essentially random, the actual concurrency will
46     * vary. Ideally, you should choose a value to accommodate as many
47 dl 1.25 * threads as will ever concurrently modify the table. Using a
48 dl 1.21 * significantly higher value than you need can waste space and time,
49     * and a significantly lower value can lead to thread contention. But
50     * overestimates and underestimates within an order of magnitude do
51 dl 1.25 * not usually have much noticeable impact. A value of one is
52 dl 1.45 * appropriate when it is known that only one thread will modify and
53     * all others will only read. Also, resizing this or any other kind of
54     * hash table is a relatively slow operation, so, when possible, it is
55     * a good idea to provide estimates of expected table sizes in
56     * constructors.
57 tim 1.1 *
58 dl 1.45 * <p>This class and its views and iterators implement all of the
59     * <em>optional</em> methods of the {@link Map} and {@link Iterator}
60     * interfaces.
61 dl 1.23 *
62 dl 1.22 * <p> Like {@link java.util.Hashtable} but unlike {@link
63     * java.util.HashMap}, this class does NOT allow <tt>null</tt> to be
64     * used as a key or value.
65 tim 1.1 *
66 dl 1.42 * <p>This class is a member of the
67     * <a href="{@docRoot}/../guide/collections/index.html">
68     * Java Collections Framework</a>.
69     *
70 dl 1.8 * @since 1.5
71     * @author Doug Lea
72 dl 1.27 * @param <K> the type of keys maintained by this map
73     * @param <V> the type of mapped values
74 dl 1.8 */
75 tim 1.1 public class ConcurrentHashMap<K, V> extends AbstractMap<K, V>
76     implements ConcurrentMap<K, V>, Cloneable, Serializable {
77 dl 1.20 private static final long serialVersionUID = 7249069246763182397L;
78 tim 1.1
79     /*
80 dl 1.4 * The basic strategy is to subdivide the table among Segments,
81     * each of which itself is a concurrently readable hash table.
82     */
83 tim 1.1
84 dl 1.4 /* ---------------- Constants -------------- */
85 tim 1.11
86 dl 1.4 /**
87 dl 1.19 * The default initial number of table slots for this table.
88 dl 1.4 * Used when not otherwise specified in constructor.
89     */
90 dl 1.41 static int DEFAULT_INITIAL_CAPACITY = 16;
91 tim 1.1
92     /**
93 dl 1.4 * The maximum capacity, used if a higher value is implicitly
94     * specified by either of the constructors with arguments. MUST
95 dl 1.21 * be a power of two <= 1<<30 to ensure that entries are indexible
96     * using ints.
97 dl 1.4 */
98 dl 1.21 static final int MAXIMUM_CAPACITY = 1 << 30;
99 tim 1.11
100 tim 1.1 /**
101 dl 1.4 * The default load factor for this table. Used when not
102     * otherwise specified in constructor.
103     */
104 tim 1.11 static final float DEFAULT_LOAD_FACTOR = 0.75f;
105 tim 1.1
106     /**
107 dl 1.4 * The default number of concurrency control segments.
108 tim 1.1 **/
109 dl 1.41 static final int DEFAULT_SEGMENTS = 16;
110 tim 1.1
111 dl 1.21 /**
112 dl 1.37 * The maximum number of segments to allow; used to bound
113     * constructor arguments.
114 dl 1.21 */
115 dl 1.41 static final int MAX_SEGMENTS = 1 << 16; // slightly conservative
116 dl 1.21
117 dl 1.4 /* ---------------- Fields -------------- */
118 tim 1.1
119     /**
120 dl 1.9 * Mask value for indexing into segments. The upper bits of a
121     * key's hash code are used to choose the segment.
122 tim 1.1 **/
123 dl 1.41 final int segmentMask;
124 tim 1.1
125     /**
126 dl 1.4 * Shift value for indexing within segments.
127 tim 1.1 **/
128 dl 1.41 final int segmentShift;
129 tim 1.1
130     /**
131 dl 1.4 * The segments, each of which is a specialized hash table
132 tim 1.1 */
133 dl 1.41 final Segment[] segments;
134 dl 1.4
135 dl 1.41 transient Set<K> keySet;
136     transient Set<Map.Entry<K,V>> entrySet;
137     transient Collection<V> values;
138 dl 1.4
139     /* ---------------- Small Utilities -------------- */
140 tim 1.1
141     /**
142 dl 1.44 * Returns a hash code for non-null Object x.
143 dl 1.37 * Uses the same hash code spreader as most other java.util hash tables.
144 dl 1.8 * @param x the object serving as a key
145     * @return the hash code
146 tim 1.1 */
147 dl 1.41 static int hash(Object x) {
148 dl 1.4 int h = x.hashCode();
149     h += ~(h << 9);
150     h ^= (h >>> 14);
151     h += (h << 4);
152     h ^= (h >>> 10);
153     return h;
154     }
155    
156 tim 1.1 /**
157 dl 1.44 * Returns the segment that should be used for key with given hash
158     * @param hash the hash code for the key
159     * @return the segment
160 tim 1.1 */
161 dl 1.41 final Segment<K,V> segmentFor(int hash) {
162 tim 1.12 return (Segment<K,V>) segments[(hash >>> segmentShift) & segmentMask];
163 dl 1.4 }
164 tim 1.1
165 dl 1.4 /* ---------------- Inner Classes -------------- */
166 tim 1.1
167     /**
168 dl 1.6 * Segments are specialized versions of hash tables. This
169 dl 1.4 * subclasses from ReentrantLock opportunistically, just to
170     * simplify some locking and avoid separate construction.
171 tim 1.1 **/
172 dl 1.41 static final class Segment<K,V> extends ReentrantLock implements Serializable {
173 dl 1.4 /*
174     * Segments maintain a table of entry lists that are ALWAYS
175     * kept in a consistent state, so can be read without locking.
176     * Next fields of nodes are immutable (final). All list
177     * additions are performed at the front of each bin. This
178     * makes it easy to check changes, and also fast to traverse.
179     * When nodes would otherwise be changed, new nodes are
180     * created to replace them. This works well for hash tables
181     * since the bin lists tend to be short. (The average length
182     * is less than two for the default load factor threshold.)
183     *
184     * Read operations can thus proceed without locking, but rely
185 dl 1.45 * on selected uses of volatiles to ensure that completed
186     * write operations performed by other threads are
187     * noticed. For most purposes, the "count" field, tracking the
188     * number of elements, serves as that volatile variable
189     * ensuring visibility. This is convenient because this field
190     * needs to be read in many read operations anyway:
191 dl 1.4 *
192 dl 1.45 * - All (unsynchronized) read operations must first read the
193 dl 1.4 * "count" field, and should not look at table entries if
194     * it is 0.
195 tim 1.11 *
196 dl 1.45 * - All (synchronized) write operations should write to
197     * the "count" field after structurally changing any bin.
198     * The operations must not take any action that could even
199     * momentarily cause a concurrent read operation to see
200     * inconsistent data. This is made easier by the nature of
201     * the read operations in Map. For example, no operation
202 dl 1.4 * can reveal that the table has grown but the threshold
203     * has not yet been updated, so there are no atomicity
204     * requirements for this with respect to reads.
205     *
206 dl 1.45 * As a guide, all critical volatile reads and writes to the
207     * count field are marked in code comments.
208 dl 1.4 */
209 tim 1.11
210 dl 1.24 private static final long serialVersionUID = 2249069246763182397L;
211    
212 dl 1.4 /**
213     * The number of elements in this segment's region.
214     **/
215     transient volatile int count;
216    
217     /**
218 dl 1.45 * Number of updates that alter the size of the table. This is
219     * used during bulk-read methods to make sure they see a
220     * consistent snapshot: If modCounts change during a traversal
221     * of segments computing size or checking contatinsValue, then
222     * we might have an inconsistent view of state so (usually)
223     * must retry.
224 dl 1.21 */
225     transient int modCount;
226    
227     /**
228 dl 1.4 * The table is rehashed when its size exceeds this threshold.
229     * (The value of this field is always (int)(capacity *
230     * loadFactor).)
231     */
232 dl 1.41 transient int threshold;
233 dl 1.4
234     /**
235 dl 1.45 * The per-segment table. Declared as a raw type, casted
236     * to HashEntry<K,V> on each use.
237 dl 1.4 */
238 dl 1.45 transient volatile HashEntry[] table;
239 dl 1.4
240     /**
241     * The load factor for the hash table. Even though this value
242     * is same for all segments, it is replicated to avoid needing
243     * links to outer object.
244     * @serial
245     */
246 dl 1.41 final float loadFactor;
247 tim 1.1
248 dl 1.4 Segment(int initialCapacity, float lf) {
249     loadFactor = lf;
250 tim 1.11 setTable(new HashEntry[initialCapacity]);
251 dl 1.4 }
252 tim 1.1
253 dl 1.4 /**
254 tim 1.11 * Set table to new HashEntry array.
255 dl 1.4 * Call only while holding lock or in constructor.
256     **/
257 dl 1.41 void setTable(HashEntry[] newTable) {
258 dl 1.45 threshold = (int)(newTable.length * loadFactor);
259 dl 1.4 table = newTable;
260 dl 1.45 }
261    
262     /**
263     * Return properly casted first entry of bin for given hash
264     */
265     HashEntry<K,V> getFirst(int hash) {
266     HashEntry[] tab = table;
267     return (HashEntry<K,V>) tab[hash & (tab.length - 1)];
268     }
269    
270     /**
271     * Read value field of an entry under lock. Called if value
272     * field ever appears to be null. This is possible only if a
273     * compiler happens to reorder a HashEntry initialization with
274     * its table assignment, which is legal under memory model
275     * but is not known to ever occur.
276     */
277     V readValueUnderLock(HashEntry<K,V> e) {
278     lock();
279     try {
280     return e.value;
281     } finally {
282     unlock();
283     }
284 tim 1.11 }
285 dl 1.4
286     /* Specialized implementations of map methods */
287 tim 1.11
288 dl 1.29 V get(Object key, int hash) {
289 dl 1.4 if (count != 0) { // read-volatile
290 dl 1.45 HashEntry<K,V> e = getFirst(hash);
291 dl 1.4 while (e != null) {
292 dl 1.45 if (e.hash == hash && key.equals(e.key)) {
293     V v = e.value;
294     if (v != null)
295     return v;
296     return readValueUnderLock(e); // recheck
297     }
298 dl 1.4 e = e.next;
299     }
300     }
301     return null;
302     }
303    
304     boolean containsKey(Object key, int hash) {
305     if (count != 0) { // read-volatile
306 dl 1.45 HashEntry<K,V> e = getFirst(hash);
307 dl 1.4 while (e != null) {
308 tim 1.11 if (e.hash == hash && key.equals(e.key))
309 dl 1.4 return true;
310     e = e.next;
311     }
312     }
313     return false;
314     }
315 tim 1.11
316 dl 1.4 boolean containsValue(Object value) {
317     if (count != 0) { // read-volatile
318 tim 1.11 HashEntry[] tab = table;
319 dl 1.4 int len = tab.length;
320 dl 1.45 for (int i = 0 ; i < len; i++) {
321     for (HashEntry<K,V> e = (HashEntry<K,V>)tab[i];
322     e != null ;
323     e = e.next) {
324     V v = e.value;
325     if (v == null) // recheck
326     v = readValueUnderLock(e);
327     if (value.equals(v))
328 dl 1.4 return true;
329 dl 1.45 }
330     }
331 dl 1.4 }
332     return false;
333     }
334    
335 dl 1.31 boolean replace(K key, int hash, V oldValue, V newValue) {
336     lock();
337     try {
338 dl 1.45 HashEntry<K,V> e = getFirst(hash);
339     while (e != null && (e.hash != hash || !key.equals(e.key)))
340 dl 1.31 e = e.next;
341 dl 1.45
342     boolean replaced = false;
343     if (e != null && oldValue.equals(e.value)) {
344     replaced = true;
345     e.value = newValue;
346 dl 1.31 }
347 dl 1.45 return replaced;
348 dl 1.33 } finally {
349     unlock();
350     }
351     }
352    
353     V replace(K key, int hash, V newValue) {
354     lock();
355     try {
356 dl 1.45 HashEntry<K,V> e = getFirst(hash);
357     while (e != null && (e.hash != hash || !key.equals(e.key)))
358 dl 1.33 e = e.next;
359 dl 1.45
360     V oldValue = null;
361     if (e != null) {
362     oldValue = e.value;
363     e.value = newValue;
364 dl 1.32 }
365 dl 1.45 return oldValue;
366 dl 1.31 } finally {
367     unlock();
368     }
369     }
370    
371 dl 1.32
372 tim 1.11 V put(K key, int hash, V value, boolean onlyIfAbsent) {
373 dl 1.4 lock();
374     try {
375 dl 1.9 int c = count;
376 dl 1.45 if (c++ > threshold) // ensure capacity
377     rehash();
378 tim 1.11 HashEntry[] tab = table;
379 dl 1.9 int index = hash & (tab.length - 1);
380 tim 1.11 HashEntry<K,V> first = (HashEntry<K,V>) tab[index];
381 dl 1.45 HashEntry<K,V> e = first;
382     while (e != null && (e.hash != hash || !key.equals(e.key)))
383     e = e.next;
384 tim 1.11
385 dl 1.45 V oldValue;
386     if (e != null) {
387     oldValue = e.value;
388     if (!onlyIfAbsent)
389     e.value = value;
390     }
391     else {
392     oldValue = null;
393     ++modCount;
394     tab[index] = new HashEntry<K,V>(key, hash, first, value);
395     count = c; // write-volatile
396 dl 1.4 }
397 dl 1.45 return oldValue;
398 tim 1.16 } finally {
399 dl 1.4 unlock();
400     }
401     }
402    
403 dl 1.45 void rehash() {
404     HashEntry[] oldTable = table;
405 dl 1.4 int oldCapacity = oldTable.length;
406     if (oldCapacity >= MAXIMUM_CAPACITY)
407 dl 1.45 return;
408 dl 1.4
409     /*
410     * Reclassify nodes in each list to new Map. Because we are
411     * using power-of-two expansion, the elements from each bin
412     * must either stay at same index, or move with a power of two
413     * offset. We eliminate unnecessary node creation by catching
414     * cases where old nodes can be reused because their next
415     * fields won't change. Statistically, at the default
416 dl 1.29 * threshold, only about one-sixth of them need cloning when
417 dl 1.4 * a table doubles. The nodes they replace will be garbage
418     * collectable as soon as they are no longer referenced by any
419     * reader thread that may be in the midst of traversing table
420     * right now.
421     */
422 tim 1.11
423     HashEntry[] newTable = new HashEntry[oldCapacity << 1];
424 dl 1.45 threshold = (int)(newTable.length * loadFactor);
425 dl 1.4 int sizeMask = newTable.length - 1;
426     for (int i = 0; i < oldCapacity ; i++) {
427     // We need to guarantee that any existing reads of old Map can
428 tim 1.11 // proceed. So we cannot yet null out each bin.
429 tim 1.12 HashEntry<K,V> e = (HashEntry<K,V>)oldTable[i];
430 tim 1.11
431 dl 1.4 if (e != null) {
432     HashEntry<K,V> next = e.next;
433     int idx = e.hash & sizeMask;
434 tim 1.11
435 dl 1.4 // Single node on list
436 tim 1.11 if (next == null)
437 dl 1.4 newTable[idx] = e;
438 tim 1.11
439     else {
440 dl 1.4 // Reuse trailing consecutive sequence at same slot
441     HashEntry<K,V> lastRun = e;
442     int lastIdx = idx;
443 tim 1.11 for (HashEntry<K,V> last = next;
444     last != null;
445 dl 1.4 last = last.next) {
446     int k = last.hash & sizeMask;
447     if (k != lastIdx) {
448     lastIdx = k;
449     lastRun = last;
450     }
451     }
452     newTable[lastIdx] = lastRun;
453 tim 1.11
454 dl 1.4 // Clone all remaining nodes
455     for (HashEntry<K,V> p = e; p != lastRun; p = p.next) {
456     int k = p.hash & sizeMask;
457 dl 1.45 HashEntry<K,V> n = (HashEntry<K,V>)newTable[k];
458     newTable[k] = new HashEntry<K,V>(p.key, p.hash,
459     n, p.value);
460 dl 1.4 }
461     }
462     }
463     }
464 dl 1.45 table = newTable;
465 dl 1.4 }
466 dl 1.6
467     /**
468     * Remove; match on key only if value null, else match both.
469     */
470 dl 1.4 V remove(Object key, int hash, Object value) {
471 tim 1.11 lock();
472 dl 1.4 try {
473 dl 1.45 int c = count - 1;
474 dl 1.4 HashEntry[] tab = table;
475 dl 1.9 int index = hash & (tab.length - 1);
476 tim 1.12 HashEntry<K,V> first = (HashEntry<K,V>)tab[index];
477 dl 1.4 HashEntry<K,V> e = first;
478 dl 1.45 while (e != null && (e.hash != hash || !key.equals(e.key)))
479 dl 1.4 e = e.next;
480 dl 1.45
481     V oldValue = null;
482     if (e != null) {
483     V v = e.value;
484     if (value == null || value.equals(v)) {
485     oldValue = v;
486     // All entries following removed node can stay
487     // in list, but all preceding ones need to be
488     // cloned.
489     ++modCount;
490     HashEntry<K,V> newFirst = e.next;
491     for (HashEntry<K,V> p = first; p != e; p = p.next)
492     newFirst = new HashEntry<K,V>(p.key, p.hash,
493     newFirst, p.value);
494     tab[index] = newFirst;
495     count = c; // write-volatile
496     }
497 dl 1.4 }
498 dl 1.9 return oldValue;
499 tim 1.16 } finally {
500 dl 1.4 unlock();
501     }
502     }
503    
504     void clear() {
505 dl 1.45 if (count != 0) {
506     lock();
507     try {
508     HashEntry[] tab = table;
509     for (int i = 0; i < tab.length ; i++)
510     tab[i] = null;
511     ++modCount;
512     count = 0; // write-volatile
513     } finally {
514     unlock();
515     }
516 dl 1.4 }
517     }
518 tim 1.1 }
519    
520     /**
521 dl 1.30 * ConcurrentHashMap list entry. Note that this is never exported
522     * out as a user-visible Map.Entry
523 tim 1.1 */
524 dl 1.41 static final class HashEntry<K,V> {
525     final K key;
526     final int hash;
527 dl 1.45 volatile V value;
528 dl 1.41 final HashEntry<K,V> next;
529 dl 1.4
530 dl 1.45 HashEntry(K key, int hash, HashEntry<K,V> next, V value) {
531     this.key = key;
532 dl 1.4 this.hash = hash;
533     this.next = next;
534 dl 1.45 this.value = value;
535 dl 1.4 }
536 tim 1.1 }
537    
538 tim 1.11
539 dl 1.4 /* ---------------- Public operations -------------- */
540 tim 1.1
541     /**
542 dl 1.44 * Creates a new, empty map with the specified initial
543 tim 1.1 * capacity and the specified load factor.
544     *
545 dl 1.19 * @param initialCapacity the initial capacity. The implementation
546     * performs internal sizing to accommodate this many elements.
547 tim 1.1 * @param loadFactor the load factor threshold, used to control resizing.
548 dl 1.19 * @param concurrencyLevel the estimated number of concurrently
549     * updating threads. The implementation performs internal sizing
550 dl 1.21 * to try to accommodate this many threads.
551 dl 1.4 * @throws IllegalArgumentException if the initial capacity is
552 dl 1.19 * negative or the load factor or concurrencyLevel are
553 dl 1.4 * nonpositive.
554     */
555 tim 1.11 public ConcurrentHashMap(int initialCapacity,
556 dl 1.19 float loadFactor, int concurrencyLevel) {
557     if (!(loadFactor > 0) || initialCapacity < 0 || concurrencyLevel <= 0)
558 dl 1.4 throw new IllegalArgumentException();
559    
560 dl 1.21 if (concurrencyLevel > MAX_SEGMENTS)
561     concurrencyLevel = MAX_SEGMENTS;
562    
563 dl 1.4 // Find power-of-two sizes best matching arguments
564     int sshift = 0;
565     int ssize = 1;
566 dl 1.19 while (ssize < concurrencyLevel) {
567 dl 1.4 ++sshift;
568     ssize <<= 1;
569     }
570 dl 1.9 segmentShift = 32 - sshift;
571 dl 1.8 segmentMask = ssize - 1;
572 tim 1.11 this.segments = new Segment[ssize];
573 dl 1.4
574     if (initialCapacity > MAXIMUM_CAPACITY)
575     initialCapacity = MAXIMUM_CAPACITY;
576     int c = initialCapacity / ssize;
577 tim 1.11 if (c * ssize < initialCapacity)
578 dl 1.4 ++c;
579     int cap = 1;
580     while (cap < c)
581     cap <<= 1;
582    
583     for (int i = 0; i < this.segments.length; ++i)
584     this.segments[i] = new Segment<K,V>(cap, loadFactor);
585 tim 1.1 }
586    
587     /**
588 dl 1.44 * Creates a new, empty map with the specified initial
589 dl 1.19 * capacity, and with default load factor and concurrencyLevel.
590 tim 1.1 *
591 dl 1.19 * @param initialCapacity The implementation performs internal
592     * sizing to accommodate this many elements.
593 dl 1.4 * @throws IllegalArgumentException if the initial capacity of
594     * elements is negative.
595 tim 1.1 */
596     public ConcurrentHashMap(int initialCapacity) {
597 dl 1.4 this(initialCapacity, DEFAULT_LOAD_FACTOR, DEFAULT_SEGMENTS);
598 tim 1.1 }
599    
600     /**
601 dl 1.44 * Creates a new, empty map with a default initial capacity,
602 dl 1.23 * load factor, and concurrencyLevel.
603 tim 1.1 */
604     public ConcurrentHashMap() {
605 dl 1.4 this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR, DEFAULT_SEGMENTS);
606 tim 1.1 }
607    
608     /**
609 dl 1.44 * Creates a new map with the same mappings as the given map. The
610 tim 1.1 * map is created with a capacity of twice the number of mappings in
611 dl 1.4 * the given map or 11 (whichever is greater), and a default load factor.
612 dl 1.40 * @param t the map
613 tim 1.1 */
614 tim 1.39 public ConcurrentHashMap(Map<? extends K, ? extends V> t) {
615 tim 1.1 this(Math.max((int) (t.size() / DEFAULT_LOAD_FACTOR) + 1,
616 dl 1.4 11),
617     DEFAULT_LOAD_FACTOR, DEFAULT_SEGMENTS);
618     putAll(t);
619 tim 1.1 }
620    
621 dl 1.4 // inherit Map javadoc
622 tim 1.1 public boolean isEmpty() {
623 dl 1.35 final Segment[] segments = this.segments;
624 dl 1.21 /*
625 dl 1.45 * We keep track of per-segment modCounts to avoid ABA
626 dl 1.21 * problems in which an element in one segment was added and
627     * in another removed during traversal, in which case the
628     * table was never actually empty at any point. Note the
629     * similar use of modCounts in the size() and containsValue()
630     * methods, which are the only other methods also susceptible
631     * to ABA problems.
632     */
633     int[] mc = new int[segments.length];
634     int mcsum = 0;
635     for (int i = 0; i < segments.length; ++i) {
636 dl 1.4 if (segments[i].count != 0)
637 tim 1.1 return false;
638 dl 1.21 else
639     mcsum += mc[i] = segments[i].modCount;
640     }
641     // If mcsum happens to be zero, then we know we got a snapshot
642     // before any modifications at all were made. This is
643     // probably common enough to bother tracking.
644     if (mcsum != 0) {
645     for (int i = 0; i < segments.length; ++i) {
646     if (segments[i].count != 0 ||
647     mc[i] != segments[i].modCount)
648     return false;
649     }
650     }
651 tim 1.1 return true;
652     }
653    
654 dl 1.21 // inherit Map javadoc
655     public int size() {
656 dl 1.35 final Segment[] segments = this.segments;
657 dl 1.45 long sum = 0;
658     long check = 0;
659 dl 1.21 int[] mc = new int[segments.length];
660 dl 1.45 // Try at most twice to get accurate count. On failure due to
661     // continuous async changes in table, resort to locking.
662     for (int k = 0; k < 2; ++k) {
663     check = 0;
664     sum = 0;
665 dl 1.21 int mcsum = 0;
666     for (int i = 0; i < segments.length; ++i) {
667     sum += segments[i].count;
668     mcsum += mc[i] = segments[i].modCount;
669     }
670     if (mcsum != 0) {
671     for (int i = 0; i < segments.length; ++i) {
672     check += segments[i].count;
673     if (mc[i] != segments[i].modCount) {
674     check = -1; // force retry
675     break;
676     }
677     }
678     }
679 dl 1.45 if (check == sum)
680     break;
681     }
682     if (check != sum) { // Resort to locking all segments
683     sum = 0;
684     for (int i = 0; i < segments.length; ++i)
685     segments[i].lock();
686     for (int i = 0; i < segments.length; ++i)
687     sum += segments[i].count;
688     for (int i = 0; i < segments.length; ++i)
689     segments[i].unlock();
690 dl 1.21 }
691 dl 1.45 if (sum > Integer.MAX_VALUE)
692     return Integer.MAX_VALUE;
693     else
694     return (int)sum;
695 dl 1.21 }
696    
697    
698 tim 1.1 /**
699     * Returns the value to which the specified key is mapped in this table.
700     *
701     * @param key a key in the table.
702     * @return the value to which the key is mapped in this table;
703 dl 1.19 * <tt>null</tt> if the key is not mapped to any value in
704 tim 1.1 * this table.
705 dl 1.8 * @throws NullPointerException if the key is
706 dl 1.19 * <tt>null</tt>.
707 tim 1.1 */
708 tim 1.11 public V get(Object key) {
709 dl 1.4 int hash = hash(key); // throws NullPointerException if key null
710 dl 1.29 return segmentFor(hash).get(key, hash);
711 tim 1.1 }
712    
713     /**
714     * Tests if the specified object is a key in this table.
715 tim 1.11 *
716 tim 1.1 * @param key possible key.
717 dl 1.19 * @return <tt>true</tt> if and only if the specified object
718 tim 1.11 * is a key in this table, as determined by the
719 dl 1.19 * <tt>equals</tt> method; <tt>false</tt> otherwise.
720 dl 1.8 * @throws NullPointerException if the key is
721 dl 1.19 * <tt>null</tt>.
722 tim 1.1 */
723     public boolean containsKey(Object key) {
724 dl 1.4 int hash = hash(key); // throws NullPointerException if key null
725 dl 1.9 return segmentFor(hash).containsKey(key, hash);
726 tim 1.1 }
727    
728     /**
729     * Returns <tt>true</tt> if this map maps one or more keys to the
730     * specified value. Note: This method requires a full internal
731     * traversal of the hash table, and so is much slower than
732     * method <tt>containsKey</tt>.
733     *
734     * @param value value whose presence in this map is to be tested.
735     * @return <tt>true</tt> if this map maps one or more keys to the
736 tim 1.11 * specified value.
737 dl 1.19 * @throws NullPointerException if the value is <tt>null</tt>.
738 tim 1.1 */
739     public boolean containsValue(Object value) {
740 tim 1.11 if (value == null)
741 dl 1.4 throw new NullPointerException();
742 dl 1.45
743     // See explanation of modCount use above
744 tim 1.1
745 dl 1.35 final Segment[] segments = this.segments;
746 dl 1.21 int[] mc = new int[segments.length];
747 dl 1.45
748     // Try at most twice without locking
749     for (int k = 0; k < 2; ++k) {
750 dl 1.21 int sum = 0;
751     int mcsum = 0;
752     for (int i = 0; i < segments.length; ++i) {
753     int c = segments[i].count;
754     mcsum += mc[i] = segments[i].modCount;
755     if (segments[i].containsValue(value))
756     return true;
757     }
758     boolean cleanSweep = true;
759     if (mcsum != 0) {
760     for (int i = 0; i < segments.length; ++i) {
761     int c = segments[i].count;
762     if (mc[i] != segments[i].modCount) {
763     cleanSweep = false;
764     break;
765     }
766     }
767     }
768     if (cleanSweep)
769     return false;
770 tim 1.1 }
771 dl 1.45 // Resort to locking all segments
772     for (int i = 0; i < segments.length; ++i)
773     segments[i].lock();
774     boolean found = false;
775     try {
776     for (int i = 0; i < segments.length; ++i) {
777     if (segments[i].containsValue(value)) {
778     found = true;
779     break;
780     }
781     }
782     } finally {
783     for (int i = 0; i < segments.length; ++i)
784     segments[i].unlock();
785     }
786     return found;
787 tim 1.1 }
788 dl 1.19
789 tim 1.1 /**
790 dl 1.18 * Legacy method testing if some key maps into the specified value
791 dl 1.23 * in this table. This method is identical in functionality to
792     * {@link #containsValue}, and exists solely to ensure
793 dl 1.19 * full compatibility with class {@link java.util.Hashtable},
794 dl 1.18 * which supported this method prior to introduction of the
795 dl 1.23 * Java Collections framework.
796 dl 1.17
797 tim 1.1 * @param value a value to search for.
798 dl 1.19 * @return <tt>true</tt> if and only if some key maps to the
799     * <tt>value</tt> argument in this table as
800 tim 1.1 * determined by the <tt>equals</tt> method;
801 dl 1.19 * <tt>false</tt> otherwise.
802     * @throws NullPointerException if the value is <tt>null</tt>.
803 tim 1.1 */
804 dl 1.4 public boolean contains(Object value) {
805 tim 1.1 return containsValue(value);
806     }
807    
808     /**
809 dl 1.19 * Maps the specified <tt>key</tt> to the specified
810     * <tt>value</tt> in this table. Neither the key nor the
811 dl 1.44 * value can be <tt>null</tt>.
812 dl 1.4 *
813 dl 1.44 * <p> The value can be retrieved by calling the <tt>get</tt> method
814 tim 1.11 * with a key that is equal to the original key.
815 dl 1.4 *
816     * @param key the table key.
817     * @param value the value.
818     * @return the previous value of the specified key in this table,
819 dl 1.19 * or <tt>null</tt> if it did not have one.
820 dl 1.8 * @throws NullPointerException if the key or value is
821 dl 1.19 * <tt>null</tt>.
822 dl 1.4 */
823 tim 1.11 public V put(K key, V value) {
824     if (value == null)
825 dl 1.4 throw new NullPointerException();
826 tim 1.11 int hash = hash(key);
827 dl 1.9 return segmentFor(hash).put(key, hash, value, false);
828 dl 1.4 }
829    
830     /**
831     * If the specified key is not already associated
832     * with a value, associate it with the given value.
833     * This is equivalent to
834     * <pre>
835 dl 1.17 * if (!map.containsKey(key))
836     * return map.put(key, value);
837     * else
838     * return map.get(key);
839 dl 1.4 * </pre>
840     * Except that the action is performed atomically.
841     * @param key key with which the specified value is to be associated.
842     * @param value value to be associated with the specified key.
843     * @return previous value associated with specified key, or <tt>null</tt>
844     * if there was no mapping for key. A <tt>null</tt> return can
845     * also indicate that the map previously associated <tt>null</tt>
846     * with the specified key, if the implementation supports
847     * <tt>null</tt> values.
848     *
849 dl 1.17 * @throws UnsupportedOperationException if the <tt>put</tt> operation is
850     * not supported by this map.
851     * @throws ClassCastException if the class of the specified key or value
852     * prevents it from being stored in this map.
853     * @throws NullPointerException if the specified key or value is
854 dl 1.4 * <tt>null</tt>.
855     *
856     **/
857 tim 1.11 public V putIfAbsent(K key, V value) {
858     if (value == null)
859 dl 1.4 throw new NullPointerException();
860 tim 1.11 int hash = hash(key);
861 dl 1.9 return segmentFor(hash).put(key, hash, value, true);
862 dl 1.4 }
863    
864    
865     /**
866 tim 1.1 * Copies all of the mappings from the specified map to this one.
867     *
868     * These mappings replace any mappings that this map had for any of the
869     * keys currently in the specified Map.
870     *
871     * @param t Mappings to be stored in this map.
872     */
873 tim 1.11 public void putAll(Map<? extends K, ? extends V> t) {
874 dl 1.23 for (Iterator<Map.Entry<? extends K, ? extends V>> it = (Iterator<Map.Entry<? extends K, ? extends V>>) t.entrySet().iterator(); it.hasNext(); ) {
875 tim 1.12 Entry<? extends K, ? extends V> e = it.next();
876 dl 1.4 put(e.getKey(), e.getValue());
877 tim 1.1 }
878 dl 1.4 }
879    
880     /**
881 tim 1.11 * Removes the key (and its corresponding value) from this
882 dl 1.4 * table. This method does nothing if the key is not in the table.
883     *
884     * @param key the key that needs to be removed.
885     * @return the value to which the key had been mapped in this table,
886 dl 1.19 * or <tt>null</tt> if the key did not have a mapping.
887 dl 1.8 * @throws NullPointerException if the key is
888 dl 1.19 * <tt>null</tt>.
889 dl 1.4 */
890     public V remove(Object key) {
891     int hash = hash(key);
892 dl 1.9 return segmentFor(hash).remove(key, hash, null);
893 dl 1.4 }
894 tim 1.1
895 dl 1.4 /**
896 dl 1.17 * Remove entry for key only if currently mapped to given value.
897     * Acts as
898     * <pre>
899     * if (map.get(key).equals(value)) {
900     * map.remove(key);
901     * return true;
902     * } else return false;
903     * </pre>
904     * except that the action is performed atomically.
905     * @param key key with which the specified value is associated.
906     * @param value value associated with the specified key.
907     * @return true if the value was removed
908     * @throws NullPointerException if the specified key is
909     * <tt>null</tt>.
910 dl 1.4 */
911 dl 1.13 public boolean remove(Object key, Object value) {
912 dl 1.4 int hash = hash(key);
913 dl 1.13 return segmentFor(hash).remove(key, hash, value) != null;
914 tim 1.1 }
915 dl 1.31
916 dl 1.32
917 dl 1.31 /**
918     * Replace entry for key only if currently mapped to given value.
919     * Acts as
920     * <pre>
921     * if (map.get(key).equals(oldValue)) {
922     * map.put(key, newValue);
923     * return true;
924     * } else return false;
925     * </pre>
926     * except that the action is performed atomically.
927     * @param key key with which the specified value is associated.
928     * @param oldValue value expected to be associated with the specified key.
929     * @param newValue value to be associated with the specified key.
930     * @return true if the value was replaced
931     * @throws NullPointerException if the specified key or values are
932     * <tt>null</tt>.
933     */
934     public boolean replace(K key, V oldValue, V newValue) {
935     if (oldValue == null || newValue == null)
936     throw new NullPointerException();
937     int hash = hash(key);
938     return segmentFor(hash).replace(key, hash, oldValue, newValue);
939 dl 1.32 }
940    
941     /**
942 dl 1.33 * Replace entry for key only if currently mapped to some value.
943 dl 1.32 * Acts as
944     * <pre>
945     * if ((map.containsKey(key)) {
946 dl 1.33 * return map.put(key, value);
947     * } else return null;
948 dl 1.32 * </pre>
949     * except that the action is performed atomically.
950     * @param key key with which the specified value is associated.
951     * @param value value to be associated with the specified key.
952 dl 1.33 * @return previous value associated with specified key, or <tt>null</tt>
953     * if there was no mapping for key.
954 dl 1.32 * @throws NullPointerException if the specified key or value is
955     * <tt>null</tt>.
956     */
957 dl 1.33 public V replace(K key, V value) {
958 dl 1.32 if (value == null)
959     throw new NullPointerException();
960     int hash = hash(key);
961 dl 1.33 return segmentFor(hash).replace(key, hash, value);
962 dl 1.31 }
963    
964 tim 1.1
965     /**
966     * Removes all mappings from this map.
967     */
968     public void clear() {
969 tim 1.11 for (int i = 0; i < segments.length; ++i)
970 dl 1.4 segments[i].clear();
971 tim 1.1 }
972    
973 dl 1.4
974 tim 1.1 /**
975     * Returns a shallow copy of this
976     * <tt>ConcurrentHashMap</tt> instance: the keys and
977     * values themselves are not cloned.
978     *
979     * @return a shallow copy of this map.
980     */
981     public Object clone() {
982 dl 1.4 // We cannot call super.clone, since it would share final
983     // segments array, and there's no way to reassign finals.
984    
985     float lf = segments[0].loadFactor;
986     int segs = segments.length;
987     int cap = (int)(size() / lf);
988     if (cap < segs) cap = segs;
989 tim 1.12 ConcurrentHashMap<K,V> t = new ConcurrentHashMap<K,V>(cap, lf, segs);
990 dl 1.4 t.putAll(this);
991     return t;
992 tim 1.1 }
993    
994     /**
995     * Returns a set view of the keys contained in this map. The set is
996     * backed by the map, so changes to the map are reflected in the set, and
997     * vice-versa. The set supports element removal, which removes the
998     * corresponding mapping from this map, via the <tt>Iterator.remove</tt>,
999     * <tt>Set.remove</tt>, <tt>removeAll</tt>, <tt>retainAll</tt>, and
1000     * <tt>clear</tt> operations. It does not support the <tt>add</tt> or
1001     * <tt>addAll</tt> operations.
1002 dl 1.14 * The returned <tt>iterator</tt> is a "weakly consistent" iterator that
1003     * will never throw {@link java.util.ConcurrentModificationException},
1004     * and guarantees to traverse elements as they existed upon
1005     * construction of the iterator, and may (but is not guaranteed to)
1006     * reflect any modifications subsequent to construction.
1007 tim 1.1 *
1008     * @return a set view of the keys contained in this map.
1009     */
1010     public Set<K> keySet() {
1011     Set<K> ks = keySet;
1012 dl 1.8 return (ks != null) ? ks : (keySet = new KeySet());
1013 tim 1.1 }
1014    
1015    
1016     /**
1017     * Returns a collection view of the values contained in this map. The
1018     * collection is backed by the map, so changes to the map are reflected in
1019     * the collection, and vice-versa. The collection supports element
1020     * removal, which removes the corresponding mapping from this map, via the
1021     * <tt>Iterator.remove</tt>, <tt>Collection.remove</tt>,
1022     * <tt>removeAll</tt>, <tt>retainAll</tt>, and <tt>clear</tt> operations.
1023     * It does not support the <tt>add</tt> or <tt>addAll</tt> operations.
1024 dl 1.14 * The returned <tt>iterator</tt> is a "weakly consistent" iterator that
1025     * will never throw {@link java.util.ConcurrentModificationException},
1026     * and guarantees to traverse elements as they existed upon
1027     * construction of the iterator, and may (but is not guaranteed to)
1028     * reflect any modifications subsequent to construction.
1029 tim 1.1 *
1030     * @return a collection view of the values contained in this map.
1031     */
1032     public Collection<V> values() {
1033     Collection<V> vs = values;
1034 dl 1.8 return (vs != null) ? vs : (values = new Values());
1035 tim 1.1 }
1036    
1037    
1038     /**
1039     * Returns a collection view of the mappings contained in this map. Each
1040     * element in the returned collection is a <tt>Map.Entry</tt>. The
1041     * collection is backed by the map, so changes to the map are reflected in
1042     * the collection, and vice-versa. The collection supports element
1043     * removal, which removes the corresponding mapping from the map, via the
1044     * <tt>Iterator.remove</tt>, <tt>Collection.remove</tt>,
1045     * <tt>removeAll</tt>, <tt>retainAll</tt>, and <tt>clear</tt> operations.
1046     * It does not support the <tt>add</tt> or <tt>addAll</tt> operations.
1047 dl 1.14 * The returned <tt>iterator</tt> is a "weakly consistent" iterator that
1048     * will never throw {@link java.util.ConcurrentModificationException},
1049     * and guarantees to traverse elements as they existed upon
1050     * construction of the iterator, and may (but is not guaranteed to)
1051     * reflect any modifications subsequent to construction.
1052 tim 1.1 *
1053     * @return a collection view of the mappings contained in this map.
1054     */
1055     public Set<Map.Entry<K,V>> entrySet() {
1056     Set<Map.Entry<K,V>> es = entrySet;
1057 dl 1.23 return (es != null) ? es : (entrySet = (Set<Map.Entry<K,V>>) (Set) new EntrySet());
1058 tim 1.1 }
1059    
1060    
1061     /**
1062     * Returns an enumeration of the keys in this table.
1063     *
1064     * @return an enumeration of the keys in this table.
1065 dl 1.23 * @see #keySet
1066 tim 1.1 */
1067 dl 1.4 public Enumeration<K> keys() {
1068 tim 1.1 return new KeyIterator();
1069     }
1070    
1071     /**
1072     * Returns an enumeration of the values in this table.
1073     *
1074     * @return an enumeration of the values in this table.
1075 dl 1.23 * @see #values
1076 tim 1.1 */
1077 dl 1.4 public Enumeration<V> elements() {
1078 tim 1.1 return new ValueIterator();
1079     }
1080    
1081 dl 1.4 /* ---------------- Iterator Support -------------- */
1082 tim 1.11
1083 dl 1.41 abstract class HashIterator {
1084     int nextSegmentIndex;
1085     int nextTableIndex;
1086     HashEntry[] currentTable;
1087     HashEntry<K, V> nextEntry;
1088 dl 1.30 HashEntry<K, V> lastReturned;
1089 tim 1.1
1090 dl 1.41 HashIterator() {
1091 dl 1.8 nextSegmentIndex = segments.length - 1;
1092 dl 1.4 nextTableIndex = -1;
1093     advance();
1094 tim 1.1 }
1095    
1096     public boolean hasMoreElements() { return hasNext(); }
1097    
1098 dl 1.41 final void advance() {
1099 dl 1.4 if (nextEntry != null && (nextEntry = nextEntry.next) != null)
1100     return;
1101 tim 1.11
1102 dl 1.4 while (nextTableIndex >= 0) {
1103 tim 1.12 if ( (nextEntry = (HashEntry<K,V>)currentTable[nextTableIndex--]) != null)
1104 dl 1.4 return;
1105     }
1106 tim 1.11
1107 dl 1.4 while (nextSegmentIndex >= 0) {
1108 tim 1.12 Segment<K,V> seg = (Segment<K,V>)segments[nextSegmentIndex--];
1109 dl 1.4 if (seg.count != 0) {
1110     currentTable = seg.table;
1111 dl 1.8 for (int j = currentTable.length - 1; j >= 0; --j) {
1112 tim 1.12 if ( (nextEntry = (HashEntry<K,V>)currentTable[j]) != null) {
1113 dl 1.8 nextTableIndex = j - 1;
1114 dl 1.4 return;
1115     }
1116 tim 1.1 }
1117     }
1118     }
1119     }
1120    
1121 dl 1.4 public boolean hasNext() { return nextEntry != null; }
1122 tim 1.1
1123 dl 1.4 HashEntry<K,V> nextEntry() {
1124     if (nextEntry == null)
1125 tim 1.1 throw new NoSuchElementException();
1126 dl 1.4 lastReturned = nextEntry;
1127     advance();
1128     return lastReturned;
1129 tim 1.1 }
1130    
1131     public void remove() {
1132     if (lastReturned == null)
1133     throw new IllegalStateException();
1134     ConcurrentHashMap.this.remove(lastReturned.key);
1135     lastReturned = null;
1136     }
1137 dl 1.4 }
1138    
1139 dl 1.41 final class KeyIterator extends HashIterator implements Iterator<K>, Enumeration<K> {
1140 dl 1.4 public K next() { return super.nextEntry().key; }
1141     public K nextElement() { return super.nextEntry().key; }
1142     }
1143    
1144 dl 1.41 final class ValueIterator extends HashIterator implements Iterator<V>, Enumeration<V> {
1145 dl 1.4 public V next() { return super.nextEntry().value; }
1146     public V nextElement() { return super.nextEntry().value; }
1147     }
1148 tim 1.1
1149 dl 1.30
1150    
1151     /**
1152 dl 1.41 * Entry iterator. Exported Entry objects must write-through
1153     * changes in setValue, even if the nodes have been cloned. So we
1154     * cannot return internal HashEntry objects. Instead, the iterator
1155     * itself acts as a forwarding pseudo-entry.
1156 dl 1.30 */
1157 dl 1.41 final class EntryIterator extends HashIterator implements Map.Entry<K,V>, Iterator<Entry<K,V>> {
1158 dl 1.30 public Map.Entry<K,V> next() {
1159     nextEntry();
1160     return this;
1161     }
1162    
1163     public K getKey() {
1164     if (lastReturned == null)
1165     throw new IllegalStateException("Entry was removed");
1166     return lastReturned.key;
1167     }
1168    
1169     public V getValue() {
1170     if (lastReturned == null)
1171     throw new IllegalStateException("Entry was removed");
1172     return ConcurrentHashMap.this.get(lastReturned.key);
1173     }
1174    
1175     public V setValue(V value) {
1176     if (lastReturned == null)
1177     throw new IllegalStateException("Entry was removed");
1178     return ConcurrentHashMap.this.put(lastReturned.key, value);
1179     }
1180    
1181     public boolean equals(Object o) {
1182 dl 1.43 // If not acting as entry, just use default.
1183     if (lastReturned == null)
1184     return super.equals(o);
1185 dl 1.30 if (!(o instanceof Map.Entry))
1186     return false;
1187 tim 1.39 Map.Entry e = (Map.Entry)o;
1188     return eq(getKey(), e.getKey()) && eq(getValue(), e.getValue());
1189     }
1190 dl 1.30
1191     public int hashCode() {
1192 dl 1.43 // If not acting as entry, just use default.
1193     if (lastReturned == null)
1194     return super.hashCode();
1195    
1196 dl 1.30 Object k = getKey();
1197     Object v = getValue();
1198     return ((k == null) ? 0 : k.hashCode()) ^
1199     ((v == null) ? 0 : v.hashCode());
1200     }
1201    
1202     public String toString() {
1203 dl 1.43 // If not acting as entry, just use default.
1204 dl 1.34 if (lastReturned == null)
1205     return super.toString();
1206     else
1207     return getKey() + "=" + getValue();
1208 dl 1.30 }
1209    
1210 dl 1.41 boolean eq(Object o1, Object o2) {
1211 dl 1.30 return (o1 == null ? o2 == null : o1.equals(o2));
1212     }
1213    
1214 tim 1.1 }
1215    
1216 dl 1.41 final class KeySet extends AbstractSet<K> {
1217 dl 1.4 public Iterator<K> iterator() {
1218     return new KeyIterator();
1219     }
1220     public int size() {
1221     return ConcurrentHashMap.this.size();
1222     }
1223     public boolean contains(Object o) {
1224     return ConcurrentHashMap.this.containsKey(o);
1225     }
1226     public boolean remove(Object o) {
1227     return ConcurrentHashMap.this.remove(o) != null;
1228     }
1229     public void clear() {
1230     ConcurrentHashMap.this.clear();
1231     }
1232 tim 1.1 }
1233    
1234 dl 1.41 final class Values extends AbstractCollection<V> {
1235 dl 1.4 public Iterator<V> iterator() {
1236     return new ValueIterator();
1237     }
1238     public int size() {
1239     return ConcurrentHashMap.this.size();
1240     }
1241     public boolean contains(Object o) {
1242     return ConcurrentHashMap.this.containsValue(o);
1243     }
1244     public void clear() {
1245     ConcurrentHashMap.this.clear();
1246     }
1247 tim 1.1 }
1248    
1249 dl 1.41 final class EntrySet extends AbstractSet<Map.Entry<K,V>> {
1250 dl 1.4 public Iterator<Map.Entry<K,V>> iterator() {
1251     return new EntryIterator();
1252     }
1253     public boolean contains(Object o) {
1254     if (!(o instanceof Map.Entry))
1255     return false;
1256     Map.Entry<K,V> e = (Map.Entry<K,V>)o;
1257     V v = ConcurrentHashMap.this.get(e.getKey());
1258     return v != null && v.equals(e.getValue());
1259     }
1260     public boolean remove(Object o) {
1261     if (!(o instanceof Map.Entry))
1262     return false;
1263     Map.Entry<K,V> e = (Map.Entry<K,V>)o;
1264 dl 1.13 return ConcurrentHashMap.this.remove(e.getKey(), e.getValue());
1265 dl 1.4 }
1266     public int size() {
1267     return ConcurrentHashMap.this.size();
1268     }
1269     public void clear() {
1270     ConcurrentHashMap.this.clear();
1271 dl 1.30 }
1272     public Object[] toArray() {
1273     // Since we don't ordinarily have distinct Entry objects, we
1274     // must pack elements using exportable SimpleEntry
1275     Collection<Map.Entry<K,V>> c = new ArrayList<Map.Entry<K,V>>(size());
1276     for (Iterator<Map.Entry<K,V>> i = iterator(); i.hasNext(); )
1277     c.add(new SimpleEntry<K,V>(i.next()));
1278     return c.toArray();
1279     }
1280     public <T> T[] toArray(T[] a) {
1281     Collection<Map.Entry<K,V>> c = new ArrayList<Map.Entry<K,V>>(size());
1282     for (Iterator<Map.Entry<K,V>> i = iterator(); i.hasNext(); )
1283     c.add(new SimpleEntry<K,V>(i.next()));
1284     return c.toArray(a);
1285     }
1286    
1287     }
1288    
1289     /**
1290     * This duplicates java.util.AbstractMap.SimpleEntry until this class
1291     * is made accessible.
1292     */
1293 dl 1.41 static final class SimpleEntry<K,V> implements Entry<K,V> {
1294 tim 1.39 K key;
1295     V value;
1296 dl 1.30
1297 tim 1.39 public SimpleEntry(K key, V value) {
1298     this.key = key;
1299 dl 1.30 this.value = value;
1300 tim 1.39 }
1301 dl 1.30
1302 tim 1.39 public SimpleEntry(Entry<K,V> e) {
1303     this.key = e.getKey();
1304 dl 1.30 this.value = e.getValue();
1305 tim 1.39 }
1306    
1307     public K getKey() {
1308     return key;
1309     }
1310 dl 1.30
1311 tim 1.39 public V getValue() {
1312     return value;
1313     }
1314    
1315     public V setValue(V value) {
1316     V oldValue = this.value;
1317     this.value = value;
1318     return oldValue;
1319     }
1320    
1321     public boolean equals(Object o) {
1322     if (!(o instanceof Map.Entry))
1323     return false;
1324     Map.Entry e = (Map.Entry)o;
1325     return eq(key, e.getKey()) && eq(value, e.getValue());
1326     }
1327    
1328     public int hashCode() {
1329     return ((key == null) ? 0 : key.hashCode()) ^
1330     ((value == null) ? 0 : value.hashCode());
1331     }
1332    
1333     public String toString() {
1334     return key + "=" + value;
1335     }
1336 dl 1.30
1337 dl 1.41 static boolean eq(Object o1, Object o2) {
1338 dl 1.30 return (o1 == null ? o2 == null : o1.equals(o2));
1339 dl 1.4 }
1340 tim 1.1 }
1341    
1342 dl 1.4 /* ---------------- Serialization Support -------------- */
1343    
1344 tim 1.1 /**
1345     * Save the state of the <tt>ConcurrentHashMap</tt>
1346     * instance to a stream (i.e.,
1347     * serialize it).
1348 dl 1.8 * @param s the stream
1349 tim 1.1 * @serialData
1350     * the key (Object) and value (Object)
1351     * for each key-value mapping, followed by a null pair.
1352     * The key-value mappings are emitted in no particular order.
1353     */
1354     private void writeObject(java.io.ObjectOutputStream s) throws IOException {
1355     s.defaultWriteObject();
1356    
1357     for (int k = 0; k < segments.length; ++k) {
1358 tim 1.12 Segment<K,V> seg = (Segment<K,V>)segments[k];
1359 dl 1.2 seg.lock();
1360     try {
1361 tim 1.11 HashEntry[] tab = seg.table;
1362 dl 1.4 for (int i = 0; i < tab.length; ++i) {
1363 tim 1.12 for (HashEntry<K,V> e = (HashEntry<K,V>)tab[i]; e != null; e = e.next) {
1364 dl 1.4 s.writeObject(e.key);
1365     s.writeObject(e.value);
1366     }
1367     }
1368 tim 1.16 } finally {
1369 dl 1.2 seg.unlock();
1370     }
1371 tim 1.1 }
1372     s.writeObject(null);
1373     s.writeObject(null);
1374     }
1375    
1376     /**
1377     * Reconstitute the <tt>ConcurrentHashMap</tt>
1378     * instance from a stream (i.e.,
1379     * deserialize it).
1380 dl 1.8 * @param s the stream
1381 tim 1.1 */
1382     private void readObject(java.io.ObjectInputStream s)
1383     throws IOException, ClassNotFoundException {
1384     s.defaultReadObject();
1385    
1386 dl 1.4 // Initialize each segment to be minimally sized, and let grow.
1387     for (int i = 0; i < segments.length; ++i) {
1388 tim 1.11 segments[i].setTable(new HashEntry[1]);
1389 dl 1.4 }
1390 tim 1.1
1391     // Read the keys and values, and put the mappings in the table
1392 dl 1.9 for (;;) {
1393 tim 1.1 K key = (K) s.readObject();
1394     V value = (V) s.readObject();
1395     if (key == null)
1396     break;
1397     put(key, value);
1398     }
1399     }
1400     }
1401 tim 1.11