ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/ConcurrentHashMap.java
Revision: 1.20
Committed: Mon Aug 25 19:27:58 2003 UTC (20 years, 9 months ago) by dl
Branch: MAIN
Changes since 1.19: +1 -0 lines
Log Message:
serialVersionUIDs

File Contents

# Content
1 /*
2 * Written by Doug Lea with assistance from members of JCP JSR-166
3 * Expert Group and released to the public domain. Use, modify, and
4 * redistribute this code in any way without acknowledgement.
5 */
6
7 package java.util.concurrent;
8 import java.util.concurrent.locks.*;
9 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 * A hash table supporting full concurrency of retrievals and
17 * adjustable expected concurrency for updates. This class obeys the
18 * same functional specification as <tt>java.util.Hashtable</tt>, and
19 * includes versions of methods corresponding to each method of
20 * <tt>Hashtable</tt> . However, even though all operations are
21 * 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 * thread safety but not on its synchronization details.
26 *
27 * <p> Retrieval operations (including <tt>get</tt>) ordinarily
28 * overlap with update operations (including <tt>put</tt> and
29 * <tt>remove</tt>). Retrievals reflect the results of the most
30 * recently <em>completed</em> update operations holding upon their
31 * onset. For aggregate operations such as <tt>putAll</tt> and
32 * <tt>clear</tt>, concurrent retrievals may reflect insertion or
33 * 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 * They do <em>not</em> throw ConcurrentModificationException.
37 * However, Iterators are designed to be used by only one thread at a
38 * time.
39 *
40 * <p> The allowed concurrency among update operations is guided by
41 * the optional <tt>concurrencyLevel</tt> constructor argument
42 * (default 16). The table is internally partitioned to permit the
43 * indicated number of concurrent updates without contention. Because
44 * placement in hash tables is essentially random, the actual
45 * concurrency will vary. Ideally, you should choose a value to
46 * accommodate as many threads as will ever concurrently access the
47 * table. Using a significantly higher value than you need can waste
48 * space and time, and a significantly lower value can lead to thread
49 * contention. But overestimates and underestimates within an order of
50 * magnitude do not usually have much noticeable impact.
51 *
52 * <p> Like Hashtable but unlike java.util.HashMap, this class does
53 * NOT allow <tt>null</tt> to be used as a key or value.
54 *
55 * @since 1.5
56 * @author Doug Lea
57 */
58 public class ConcurrentHashMap<K, V> extends AbstractMap<K, V>
59 implements ConcurrentMap<K, V>, Cloneable, Serializable {
60 private static final long serialVersionUID = 7249069246763182397L;
61
62 /*
63 * The basic strategy is to subdivide the table among Segments,
64 * each of which itself is a concurrently readable hash table.
65 */
66
67 /* ---------------- Constants -------------- */
68
69 /**
70 * The default initial number of table slots for this table.
71 * Used when not otherwise specified in constructor.
72 */
73 private static int DEFAULT_INITIAL_CAPACITY = 16;
74
75 /**
76 * The maximum capacity, used if a higher value is implicitly
77 * specified by either of the constructors with arguments. MUST
78 * be a power of two <= 1<<30.
79 */
80 static final int MAXIMUM_CAPACITY = 1 << 30;
81
82 /**
83 * The default load factor for this table. Used when not
84 * otherwise specified in constructor.
85 */
86 static final float DEFAULT_LOAD_FACTOR = 0.75f;
87
88 /**
89 * The default number of concurrency control segments.
90 **/
91 private static final int DEFAULT_SEGMENTS = 16;
92
93 /* ---------------- Fields -------------- */
94
95 /**
96 * Mask value for indexing into segments. The upper bits of a
97 * key's hash code are used to choose the segment.
98 **/
99 private final int segmentMask;
100
101 /**
102 * Shift value for indexing within segments.
103 **/
104 private final int segmentShift;
105
106 /**
107 * The segments, each of which is a specialized hash table
108 */
109 private final Segment[] segments;
110
111 private transient Set<K> keySet;
112 private transient Set<Map.Entry<K,V>> entrySet;
113 private transient Collection<V> values;
114
115 /* ---------------- Small Utilities -------------- */
116
117 /**
118 * Return a hash code for non-null Object x.
119 * Uses the same hash code spreader as most other j.u hash tables.
120 * @param x the object serving as a key
121 * @return the hash code
122 */
123 private static int hash(Object x) {
124 int h = x.hashCode();
125 h += ~(h << 9);
126 h ^= (h >>> 14);
127 h += (h << 4);
128 h ^= (h >>> 10);
129 return h;
130 }
131
132 /**
133 * Return the segment that should be used for key with given hash
134 */
135 private Segment<K,V> segmentFor(int hash) {
136 return (Segment<K,V>) segments[(hash >>> segmentShift) & segmentMask];
137 }
138
139 /* ---------------- Inner Classes -------------- */
140
141 /**
142 * Segments are specialized versions of hash tables. This
143 * subclasses from ReentrantLock opportunistically, just to
144 * simplify some locking and avoid separate construction.
145 **/
146 private static final class Segment<K,V> extends ReentrantLock implements Serializable {
147 /*
148 * Segments maintain a table of entry lists that are ALWAYS
149 * kept in a consistent state, so can be read without locking.
150 * Next fields of nodes are immutable (final). All list
151 * additions are performed at the front of each bin. This
152 * makes it easy to check changes, and also fast to traverse.
153 * When nodes would otherwise be changed, new nodes are
154 * created to replace them. This works well for hash tables
155 * since the bin lists tend to be short. (The average length
156 * is less than two for the default load factor threshold.)
157 *
158 * Read operations can thus proceed without locking, but rely
159 * on a memory barrier to ensure that completed write
160 * operations performed by other threads are
161 * noticed. Conveniently, the "count" field, tracking the
162 * number of elements, can also serve as the volatile variable
163 * providing proper read/write barriers. This is convenient
164 * because this field needs to be read in many read operations
165 * anyway.
166 *
167 * Implementors note. The basic rules for all this are:
168 *
169 * - All unsynchronized read operations must first read the
170 * "count" field, and should not look at table entries if
171 * it is 0.
172 *
173 * - All synchronized write operations should write to
174 * the "count" field after updating. The operations must not
175 * take any action that could even momentarily cause
176 * a concurrent read operation to see inconsistent
177 * data. This is made easier by the nature of the read
178 * operations in Map. For example, no operation
179 * can reveal that the table has grown but the threshold
180 * has not yet been updated, so there are no atomicity
181 * requirements for this with respect to reads.
182 *
183 * As a guide, all critical volatile reads and writes are marked
184 * in code comments.
185 */
186
187 /**
188 * The number of elements in this segment's region.
189 **/
190 transient volatile int count;
191
192 /**
193 * The table is rehashed when its size exceeds this threshold.
194 * (The value of this field is always (int)(capacity *
195 * loadFactor).)
196 */
197 private transient int threshold;
198
199 /**
200 * The per-segment table
201 */
202 transient HashEntry[] table;
203
204 /**
205 * The load factor for the hash table. Even though this value
206 * is same for all segments, it is replicated to avoid needing
207 * links to outer object.
208 * @serial
209 */
210 private final float loadFactor;
211
212 Segment(int initialCapacity, float lf) {
213 loadFactor = lf;
214 setTable(new HashEntry[initialCapacity]);
215 }
216
217 /**
218 * Set table to new HashEntry array.
219 * Call only while holding lock or in constructor.
220 **/
221 private void setTable(HashEntry[] newTable) {
222 table = newTable;
223 threshold = (int)(newTable.length * loadFactor);
224 count = count; // write-volatile
225 }
226
227 /* Specialized implementations of map methods */
228
229 V get(K key, int hash) {
230 if (count != 0) { // read-volatile
231 HashEntry[] tab = table;
232 int index = hash & (tab.length - 1);
233 HashEntry<K,V> e = (HashEntry<K,V>) tab[index];
234 while (e != null) {
235 if (e.hash == hash && key.equals(e.key))
236 return e.value;
237 e = e.next;
238 }
239 }
240 return null;
241 }
242
243 boolean containsKey(Object key, int hash) {
244 if (count != 0) { // read-volatile
245 HashEntry[] tab = table;
246 int index = hash & (tab.length - 1);
247 HashEntry<K,V> e = (HashEntry<K,V>) tab[index];
248 while (e != null) {
249 if (e.hash == hash && key.equals(e.key))
250 return true;
251 e = e.next;
252 }
253 }
254 return false;
255 }
256
257 boolean containsValue(Object value) {
258 if (count != 0) { // read-volatile
259 HashEntry[] tab = table;
260 int len = tab.length;
261 for (int i = 0 ; i < len; i++)
262 for (HashEntry<K,V> e = (HashEntry<K,V>)tab[i] ; e != null ; e = e.next)
263 if (value.equals(e.value))
264 return true;
265 }
266 return false;
267 }
268
269 V put(K key, int hash, V value, boolean onlyIfAbsent) {
270 lock();
271 try {
272 int c = count;
273 HashEntry[] tab = table;
274 int index = hash & (tab.length - 1);
275 HashEntry<K,V> first = (HashEntry<K,V>) tab[index];
276
277 for (HashEntry<K,V> e = first; e != null; e = (HashEntry<K,V>) e.next) {
278 if (e.hash == hash && key.equals(e.key)) {
279 V oldValue = e.value;
280 if (!onlyIfAbsent)
281 e.value = value;
282 count = c; // write-volatile
283 return oldValue;
284 }
285 }
286
287 tab[index] = new HashEntry<K,V>(hash, key, value, first);
288 ++c;
289 count = c; // write-volatile
290 if (c > threshold)
291 setTable(rehash(tab));
292 return null;
293 } finally {
294 unlock();
295 }
296 }
297
298 private HashEntry[] rehash(HashEntry[] oldTable) {
299 int oldCapacity = oldTable.length;
300 if (oldCapacity >= MAXIMUM_CAPACITY)
301 return oldTable;
302
303 /*
304 * Reclassify nodes in each list to new Map. Because we are
305 * using power-of-two expansion, the elements from each bin
306 * must either stay at same index, or move with a power of two
307 * offset. We eliminate unnecessary node creation by catching
308 * cases where old nodes can be reused because their next
309 * fields won't change. Statistically, at the default
310 * threshhold, only about one-sixth of them need cloning when
311 * a table doubles. The nodes they replace will be garbage
312 * collectable as soon as they are no longer referenced by any
313 * reader thread that may be in the midst of traversing table
314 * right now.
315 */
316
317 HashEntry[] newTable = new HashEntry[oldCapacity << 1];
318 int sizeMask = newTable.length - 1;
319 for (int i = 0; i < oldCapacity ; i++) {
320 // We need to guarantee that any existing reads of old Map can
321 // proceed. So we cannot yet null out each bin.
322 HashEntry<K,V> e = (HashEntry<K,V>)oldTable[i];
323
324 if (e != null) {
325 HashEntry<K,V> next = e.next;
326 int idx = e.hash & sizeMask;
327
328 // Single node on list
329 if (next == null)
330 newTable[idx] = e;
331
332 else {
333 // Reuse trailing consecutive sequence at same slot
334 HashEntry<K,V> lastRun = e;
335 int lastIdx = idx;
336 for (HashEntry<K,V> last = next;
337 last != null;
338 last = last.next) {
339 int k = last.hash & sizeMask;
340 if (k != lastIdx) {
341 lastIdx = k;
342 lastRun = last;
343 }
344 }
345 newTable[lastIdx] = lastRun;
346
347 // Clone all remaining nodes
348 for (HashEntry<K,V> p = e; p != lastRun; p = p.next) {
349 int k = p.hash & sizeMask;
350 newTable[k] = new HashEntry<K,V>(p.hash,
351 p.key,
352 p.value,
353 (HashEntry<K,V>) newTable[k]);
354 }
355 }
356 }
357 }
358 return newTable;
359 }
360
361 /**
362 * Remove; match on key only if value null, else match both.
363 */
364 V remove(Object key, int hash, Object value) {
365 lock();
366 try {
367 int c = count;
368 HashEntry[] tab = table;
369 int index = hash & (tab.length - 1);
370 HashEntry<K,V> first = (HashEntry<K,V>)tab[index];
371
372 HashEntry<K,V> e = first;
373 for (;;) {
374 if (e == null)
375 return null;
376 if (e.hash == hash && key.equals(e.key))
377 break;
378 e = e.next;
379 }
380
381 V oldValue = e.value;
382 if (value != null && !value.equals(oldValue))
383 return null;
384
385 // All entries following removed node can stay in list, but
386 // all preceeding ones need to be cloned.
387 HashEntry<K,V> newFirst = e.next;
388 for (HashEntry<K,V> p = first; p != e; p = p.next)
389 newFirst = new HashEntry<K,V>(p.hash, p.key,
390 p.value, newFirst);
391 tab[index] = newFirst;
392 count = c-1; // write-volatile
393 return oldValue;
394 } finally {
395 unlock();
396 }
397 }
398
399 void clear() {
400 lock();
401 try {
402 HashEntry[] tab = table;
403 for (int i = 0; i < tab.length ; i++)
404 tab[i] = null;
405 count = 0; // write-volatile
406 } finally {
407 unlock();
408 }
409 }
410 }
411
412 /**
413 * ConcurrentReaderHashMap list entry.
414 */
415 private static class HashEntry<K,V> implements Entry<K,V> {
416 private final K key;
417 private V value;
418 private final int hash;
419 private final HashEntry<K,V> next;
420
421 HashEntry(int hash, K key, V value, HashEntry<K,V> next) {
422 this.value = value;
423 this.hash = hash;
424 this.key = key;
425 this.next = next;
426 }
427
428 public K getKey() {
429 return key;
430 }
431
432 public V getValue() {
433 return value;
434 }
435
436 public V setValue(V newValue) {
437 // We aren't required to, and don't provide any
438 // visibility barriers for setting value.
439 if (newValue == null)
440 throw new NullPointerException();
441 V oldValue = this.value;
442 this.value = newValue;
443 return oldValue;
444 }
445
446 public boolean equals(Object o) {
447 if (!(o instanceof Entry))
448 return false;
449 Entry<K,V> e = (Entry<K,V>)o;
450 return (key.equals(e.getKey()) && value.equals(e.getValue()));
451 }
452
453 public int hashCode() {
454 return key.hashCode() ^ value.hashCode();
455 }
456
457 public String toString() {
458 return key + "=" + value;
459 }
460 }
461
462
463 /* ---------------- Public operations -------------- */
464
465 /**
466 * Constructs a new, empty map with the specified initial
467 * capacity and the specified load factor.
468 *
469 * @param initialCapacity the initial capacity. The implementation
470 * performs internal sizing to accommodate this many elements.
471 * @param loadFactor the load factor threshold, used to control resizing.
472 * @param concurrencyLevel the estimated number of concurrently
473 * updating threads. The implementation performs internal sizing
474 * to accommodate this many threads.
475 * @throws IllegalArgumentException if the initial capacity is
476 * negative or the load factor or concurrencyLevel are
477 * nonpositive.
478 */
479 public ConcurrentHashMap(int initialCapacity,
480 float loadFactor, int concurrencyLevel) {
481 if (!(loadFactor > 0) || initialCapacity < 0 || concurrencyLevel <= 0)
482 throw new IllegalArgumentException();
483
484 // Find power-of-two sizes best matching arguments
485 int sshift = 0;
486 int ssize = 1;
487 while (ssize < concurrencyLevel) {
488 ++sshift;
489 ssize <<= 1;
490 }
491 segmentShift = 32 - sshift;
492 segmentMask = ssize - 1;
493 this.segments = new Segment[ssize];
494
495 if (initialCapacity > MAXIMUM_CAPACITY)
496 initialCapacity = MAXIMUM_CAPACITY;
497 int c = initialCapacity / ssize;
498 if (c * ssize < initialCapacity)
499 ++c;
500 int cap = 1;
501 while (cap < c)
502 cap <<= 1;
503
504 for (int i = 0; i < this.segments.length; ++i)
505 this.segments[i] = new Segment<K,V>(cap, loadFactor);
506 }
507
508 /**
509 * Constructs a new, empty map with the specified initial
510 * capacity, and with default load factor and concurrencyLevel.
511 *
512 * @param initialCapacity The implementation performs internal
513 * sizing to accommodate this many elements.
514 * @throws IllegalArgumentException if the initial capacity of
515 * elements is negative.
516 */
517 public ConcurrentHashMap(int initialCapacity) {
518 this(initialCapacity, DEFAULT_LOAD_FACTOR, DEFAULT_SEGMENTS);
519 }
520
521 /**
522 * Constructs a new, empty map with a default initial capacity,
523 * load factor, and number of concurrencyLevel.
524 */
525 public ConcurrentHashMap() {
526 this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR, DEFAULT_SEGMENTS);
527 }
528
529 /**
530 * Constructs a new map with the same mappings as the given map. The
531 * map is created with a capacity of twice the number of mappings in
532 * the given map or 11 (whichever is greater), and a default load factor.
533 */
534 public <A extends K, B extends V> ConcurrentHashMap(Map<A,B> t) {
535 this(Math.max((int) (t.size() / DEFAULT_LOAD_FACTOR) + 1,
536 11),
537 DEFAULT_LOAD_FACTOR, DEFAULT_SEGMENTS);
538 putAll(t);
539 }
540
541 // inherit Map javadoc
542 public int size() {
543 int c = 0;
544 for (int i = 0; i < segments.length; ++i)
545 c += segments[i].count;
546 return c;
547 }
548
549 // inherit Map javadoc
550 public boolean isEmpty() {
551 for (int i = 0; i < segments.length; ++i)
552 if (segments[i].count != 0)
553 return false;
554 return true;
555 }
556
557 /**
558 * Returns the value to which the specified key is mapped in this table.
559 *
560 * @param key a key in the table.
561 * @return the value to which the key is mapped in this table;
562 * <tt>null</tt> if the key is not mapped to any value in
563 * this table.
564 * @throws NullPointerException if the key is
565 * <tt>null</tt>.
566 * @see #put(Object, Object)
567 */
568 public V get(Object key) {
569 int hash = hash(key); // throws NullPointerException if key null
570 return segmentFor(hash).get((K) key, hash);
571 }
572
573 /**
574 * Tests if the specified object is a key in this table.
575 *
576 * @param key possible key.
577 * @return <tt>true</tt> if and only if the specified object
578 * is a key in this table, as determined by the
579 * <tt>equals</tt> method; <tt>false</tt> otherwise.
580 * @throws NullPointerException if the key is
581 * <tt>null</tt>.
582 * @see #contains(Object)
583 */
584 public boolean containsKey(Object key) {
585 int hash = hash(key); // throws NullPointerException if key null
586 return segmentFor(hash).containsKey(key, hash);
587 }
588
589 /**
590 * Returns <tt>true</tt> if this map maps one or more keys to the
591 * specified value. Note: This method requires a full internal
592 * traversal of the hash table, and so is much slower than
593 * method <tt>containsKey</tt>.
594 *
595 * @param value value whose presence in this map is to be tested.
596 * @return <tt>true</tt> if this map maps one or more keys to the
597 * specified value.
598 * @throws NullPointerException if the value is <tt>null</tt>.
599 */
600 public boolean containsValue(Object value) {
601 if (value == null)
602 throw new NullPointerException();
603
604 for (int i = 0; i < segments.length; ++i) {
605 if (segments[i].containsValue(value))
606 return true;
607 }
608 return false;
609 }
610
611 /**
612 * Legacy method testing if some key maps into the specified value
613 * in this table. This operation is more expensive than the
614 * <tt>containsKey</tt> method.
615 *
616 * <p> Note that this method is identical in functionality to
617 * <tt>containsValue</tt>, This method esists solely to ensure
618 * full compatibility with class {@link java.util.Hashtable},
619 * which supported this method prior to introduction of the
620 * collections framework.
621
622 * @param value a value to search for.
623 * @return <tt>true</tt> if and only if some key maps to the
624 * <tt>value</tt> argument in this table as
625 * determined by the <tt>equals</tt> method;
626 * <tt>false</tt> otherwise.
627 * @throws NullPointerException if the value is <tt>null</tt>.
628 * @see #containsKey(Object)
629 * @see #containsValue(Object)
630 * @see Map
631 */
632 public boolean contains(Object value) {
633 return containsValue(value);
634 }
635
636 /**
637 * Maps the specified <tt>key</tt> to the specified
638 * <tt>value</tt> in this table. Neither the key nor the
639 * value can be <tt>null</tt>. <p>
640 *
641 * The value can be retrieved by calling the <tt>get</tt> method
642 * with a key that is equal to the original key.
643 *
644 * @param key the table key.
645 * @param value the value.
646 * @return the previous value of the specified key in this table,
647 * or <tt>null</tt> if it did not have one.
648 * @throws NullPointerException if the key or value is
649 * <tt>null</tt>.
650 * @see Object#equals(Object)
651 * @see #get(Object)
652 */
653 public V put(K key, V value) {
654 if (value == null)
655 throw new NullPointerException();
656 int hash = hash(key);
657 return segmentFor(hash).put(key, hash, value, false);
658 }
659
660 /**
661 * If the specified key is not already associated
662 * with a value, associate it with the given value.
663 * This is equivalent to
664 * <pre>
665 * if (!map.containsKey(key))
666 * return map.put(key, value);
667 * else
668 * return map.get(key);
669 * </pre>
670 * Except that the action is performed atomically.
671 * @param key key with which the specified value is to be associated.
672 * @param value value to be associated with the specified key.
673 * @return previous value associated with specified key, or <tt>null</tt>
674 * if there was no mapping for key. A <tt>null</tt> return can
675 * also indicate that the map previously associated <tt>null</tt>
676 * with the specified key, if the implementation supports
677 * <tt>null</tt> values.
678 *
679 * @throws UnsupportedOperationException if the <tt>put</tt> operation is
680 * not supported by this map.
681 * @throws ClassCastException if the class of the specified key or value
682 * prevents it from being stored in this map.
683 * @throws NullPointerException if the specified key or value is
684 * <tt>null</tt>.
685 *
686 **/
687 public V putIfAbsent(K key, V value) {
688 if (value == null)
689 throw new NullPointerException();
690 int hash = hash(key);
691 return segmentFor(hash).put(key, hash, value, true);
692 }
693
694
695 /**
696 * Copies all of the mappings from the specified map to this one.
697 *
698 * These mappings replace any mappings that this map had for any of the
699 * keys currently in the specified Map.
700 *
701 * @param t Mappings to be stored in this map.
702 */
703 public void putAll(Map<? extends K, ? extends V> t) {
704 Iterator<Map.Entry<? extends K, ? extends V>> it = t.entrySet().iterator();
705 while (it.hasNext()) {
706 Entry<? extends K, ? extends V> e = it.next();
707 put(e.getKey(), e.getValue());
708 }
709 }
710
711 /**
712 * Removes the key (and its corresponding value) from this
713 * table. This method does nothing if the key is not in the table.
714 *
715 * @param key the key that needs to be removed.
716 * @return the value to which the key had been mapped in this table,
717 * or <tt>null</tt> if the key did not have a mapping.
718 * @throws NullPointerException if the key is
719 * <tt>null</tt>.
720 */
721 public V remove(Object key) {
722 int hash = hash(key);
723 return segmentFor(hash).remove(key, hash, null);
724 }
725
726 /**
727 * Remove entry for key only if currently mapped to given value.
728 * Acts as
729 * <pre>
730 * if (map.get(key).equals(value)) {
731 * map.remove(key);
732 * return true;
733 * } else return false;
734 * </pre>
735 * except that the action is performed atomically.
736 * @param key key with which the specified value is associated.
737 * @param value value associated with the specified key.
738 * @return true if the value was removed
739 * @throws NullPointerException if the specified key is
740 * <tt>null</tt>.
741 */
742 public boolean remove(Object key, Object value) {
743 int hash = hash(key);
744 return segmentFor(hash).remove(key, hash, value) != null;
745 }
746
747 /**
748 * Removes all mappings from this map.
749 */
750 public void clear() {
751 for (int i = 0; i < segments.length; ++i)
752 segments[i].clear();
753 }
754
755
756 /**
757 * Returns a shallow copy of this
758 * <tt>ConcurrentHashMap</tt> instance: the keys and
759 * values themselves are not cloned.
760 *
761 * @return a shallow copy of this map.
762 */
763 public Object clone() {
764 // We cannot call super.clone, since it would share final
765 // segments array, and there's no way to reassign finals.
766
767 float lf = segments[0].loadFactor;
768 int segs = segments.length;
769 int cap = (int)(size() / lf);
770 if (cap < segs) cap = segs;
771 ConcurrentHashMap<K,V> t = new ConcurrentHashMap<K,V>(cap, lf, segs);
772 t.putAll(this);
773 return t;
774 }
775
776 /**
777 * Returns a set view of the keys contained in this map. The set is
778 * backed by the map, so changes to the map are reflected in the set, and
779 * vice-versa. The set supports element removal, which removes the
780 * corresponding mapping from this map, via the <tt>Iterator.remove</tt>,
781 * <tt>Set.remove</tt>, <tt>removeAll</tt>, <tt>retainAll</tt>, and
782 * <tt>clear</tt> operations. It does not support the <tt>add</tt> or
783 * <tt>addAll</tt> operations.
784 * The returned <tt>iterator</tt> is a "weakly consistent" iterator that
785 * will never throw {@link java.util.ConcurrentModificationException},
786 * and guarantees to traverse elements as they existed upon
787 * construction of the iterator, and may (but is not guaranteed to)
788 * reflect any modifications subsequent to construction.
789 *
790 * @return a set view of the keys contained in this map.
791 */
792 public Set<K> keySet() {
793 Set<K> ks = keySet;
794 return (ks != null) ? ks : (keySet = new KeySet());
795 }
796
797
798 /**
799 * Returns a collection view of the values contained in this map. The
800 * collection is backed by the map, so changes to the map are reflected in
801 * the collection, and vice-versa. The collection supports element
802 * removal, which removes the corresponding mapping from this map, via the
803 * <tt>Iterator.remove</tt>, <tt>Collection.remove</tt>,
804 * <tt>removeAll</tt>, <tt>retainAll</tt>, and <tt>clear</tt> operations.
805 * It does not support the <tt>add</tt> or <tt>addAll</tt> operations.
806 * The returned <tt>iterator</tt> is a "weakly consistent" iterator that
807 * will never throw {@link java.util.ConcurrentModificationException},
808 * and guarantees to traverse elements as they existed upon
809 * construction of the iterator, and may (but is not guaranteed to)
810 * reflect any modifications subsequent to construction.
811 *
812 * @return a collection view of the values contained in this map.
813 */
814 public Collection<V> values() {
815 Collection<V> vs = values;
816 return (vs != null) ? vs : (values = new Values());
817 }
818
819
820 /**
821 * Returns a collection view of the mappings contained in this map. Each
822 * element in the returned collection is a <tt>Map.Entry</tt>. The
823 * collection is backed by the map, so changes to the map are reflected in
824 * the collection, and vice-versa. The collection supports element
825 * removal, which removes the corresponding mapping from the map, via the
826 * <tt>Iterator.remove</tt>, <tt>Collection.remove</tt>,
827 * <tt>removeAll</tt>, <tt>retainAll</tt>, and <tt>clear</tt> operations.
828 * It does not support the <tt>add</tt> or <tt>addAll</tt> operations.
829 * The returned <tt>iterator</tt> is a "weakly consistent" iterator that
830 * will never throw {@link java.util.ConcurrentModificationException},
831 * and guarantees to traverse elements as they existed upon
832 * construction of the iterator, and may (but is not guaranteed to)
833 * reflect any modifications subsequent to construction.
834 *
835 * @return a collection view of the mappings contained in this map.
836 */
837 public Set<Map.Entry<K,V>> entrySet() {
838 Set<Map.Entry<K,V>> es = entrySet;
839 return (es != null) ? es : (entrySet = new EntrySet());
840 }
841
842
843 /**
844 * Returns an enumeration of the keys in this table.
845 *
846 * @return an enumeration of the keys in this table.
847 * @see Enumeration
848 * @see #elements()
849 * @see #keySet()
850 * @see Map
851 */
852 public Enumeration<K> keys() {
853 return new KeyIterator();
854 }
855
856 /**
857 * Returns an enumeration of the values in this table.
858 * Use the Enumeration methods on the returned object to fetch the elements
859 * sequentially.
860 *
861 * @return an enumeration of the values in this table.
862 * @see java.util.Enumeration
863 * @see #keys()
864 * @see #values()
865 * @see Map
866 */
867 public Enumeration<V> elements() {
868 return new ValueIterator();
869 }
870
871 /* ---------------- Iterator Support -------------- */
872
873 private abstract class HashIterator {
874 private int nextSegmentIndex;
875 private int nextTableIndex;
876 private HashEntry[] currentTable;
877 private HashEntry<K, V> nextEntry;
878 private HashEntry<K, V> lastReturned;
879
880 private HashIterator() {
881 nextSegmentIndex = segments.length - 1;
882 nextTableIndex = -1;
883 advance();
884 }
885
886 public boolean hasMoreElements() { return hasNext(); }
887
888 private void advance() {
889 if (nextEntry != null && (nextEntry = nextEntry.next) != null)
890 return;
891
892 while (nextTableIndex >= 0) {
893 if ( (nextEntry = (HashEntry<K,V>)currentTable[nextTableIndex--]) != null)
894 return;
895 }
896
897 while (nextSegmentIndex >= 0) {
898 Segment<K,V> seg = (Segment<K,V>)segments[nextSegmentIndex--];
899 if (seg.count != 0) {
900 currentTable = seg.table;
901 for (int j = currentTable.length - 1; j >= 0; --j) {
902 if ( (nextEntry = (HashEntry<K,V>)currentTable[j]) != null) {
903 nextTableIndex = j - 1;
904 return;
905 }
906 }
907 }
908 }
909 }
910
911 public boolean hasNext() { return nextEntry != null; }
912
913 HashEntry<K,V> nextEntry() {
914 if (nextEntry == null)
915 throw new NoSuchElementException();
916 lastReturned = nextEntry;
917 advance();
918 return lastReturned;
919 }
920
921 public void remove() {
922 if (lastReturned == null)
923 throw new IllegalStateException();
924 ConcurrentHashMap.this.remove(lastReturned.key);
925 lastReturned = null;
926 }
927 }
928
929 private class KeyIterator extends HashIterator implements Iterator<K>, Enumeration<K> {
930 public K next() { return super.nextEntry().key; }
931 public K nextElement() { return super.nextEntry().key; }
932 }
933
934 private class ValueIterator extends HashIterator implements Iterator<V>, Enumeration<V> {
935 public V next() { return super.nextEntry().value; }
936 public V nextElement() { return super.nextEntry().value; }
937 }
938
939 private class EntryIterator extends HashIterator implements Iterator<Entry<K,V>> {
940 public Map.Entry<K,V> next() { return super.nextEntry(); }
941 }
942
943 private class KeySet extends AbstractSet<K> {
944 public Iterator<K> iterator() {
945 return new KeyIterator();
946 }
947 public int size() {
948 return ConcurrentHashMap.this.size();
949 }
950 public boolean contains(Object o) {
951 return ConcurrentHashMap.this.containsKey(o);
952 }
953 public boolean remove(Object o) {
954 return ConcurrentHashMap.this.remove(o) != null;
955 }
956 public void clear() {
957 ConcurrentHashMap.this.clear();
958 }
959 }
960
961 private class Values extends AbstractCollection<V> {
962 public Iterator<V> iterator() {
963 return new ValueIterator();
964 }
965 public int size() {
966 return ConcurrentHashMap.this.size();
967 }
968 public boolean contains(Object o) {
969 return ConcurrentHashMap.this.containsValue(o);
970 }
971 public void clear() {
972 ConcurrentHashMap.this.clear();
973 }
974 }
975
976 private class EntrySet extends AbstractSet<Map.Entry<K,V>> {
977 public Iterator<Map.Entry<K,V>> iterator() {
978 return new EntryIterator();
979 }
980 public boolean contains(Object o) {
981 if (!(o instanceof Map.Entry))
982 return false;
983 Map.Entry<K,V> e = (Map.Entry<K,V>)o;
984 V v = ConcurrentHashMap.this.get(e.getKey());
985 return v != null && v.equals(e.getValue());
986 }
987 public boolean remove(Object o) {
988 if (!(o instanceof Map.Entry))
989 return false;
990 Map.Entry<K,V> e = (Map.Entry<K,V>)o;
991 return ConcurrentHashMap.this.remove(e.getKey(), e.getValue());
992 }
993 public int size() {
994 return ConcurrentHashMap.this.size();
995 }
996 public void clear() {
997 ConcurrentHashMap.this.clear();
998 }
999 }
1000
1001 /* ---------------- Serialization Support -------------- */
1002
1003 /**
1004 * Save the state of the <tt>ConcurrentHashMap</tt>
1005 * instance to a stream (i.e.,
1006 * serialize it).
1007 * @param s the stream
1008 * @serialData
1009 * the key (Object) and value (Object)
1010 * for each key-value mapping, followed by a null pair.
1011 * The key-value mappings are emitted in no particular order.
1012 */
1013 private void writeObject(java.io.ObjectOutputStream s) throws IOException {
1014 s.defaultWriteObject();
1015
1016 for (int k = 0; k < segments.length; ++k) {
1017 Segment<K,V> seg = (Segment<K,V>)segments[k];
1018 seg.lock();
1019 try {
1020 HashEntry[] tab = seg.table;
1021 for (int i = 0; i < tab.length; ++i) {
1022 for (HashEntry<K,V> e = (HashEntry<K,V>)tab[i]; e != null; e = e.next) {
1023 s.writeObject(e.key);
1024 s.writeObject(e.value);
1025 }
1026 }
1027 } finally {
1028 seg.unlock();
1029 }
1030 }
1031 s.writeObject(null);
1032 s.writeObject(null);
1033 }
1034
1035 /**
1036 * Reconstitute the <tt>ConcurrentHashMap</tt>
1037 * instance from a stream (i.e.,
1038 * deserialize it).
1039 * @param s the stream
1040 */
1041 private void readObject(java.io.ObjectInputStream s)
1042 throws IOException, ClassNotFoundException {
1043 s.defaultReadObject();
1044
1045 // Initialize each segment to be minimally sized, and let grow.
1046 for (int i = 0; i < segments.length; ++i) {
1047 segments[i].setTable(new HashEntry[1]);
1048 }
1049
1050 // Read the keys and values, and put the mappings in the table
1051 for (;;) {
1052 K key = (K) s.readObject();
1053 V value = (V) s.readObject();
1054 if (key == null)
1055 break;
1056 put(key, value);
1057 }
1058 }
1059 }
1060