ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/ConcurrentHashMap.java
Revision: 1.72
Committed: Sat May 28 13:31:22 2005 UTC (19 years ago) by dl
Branch: MAIN
Changes since 1.71: +16 -10 lines
Log Message:
Reduce generics warnings

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