1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package org.jboss.netty.util.internal;
22
23 import java.util.AbstractCollection;
24 import java.util.AbstractMap;
25 import java.util.AbstractSet;
26 import java.util.Collection;
27 import java.util.ConcurrentModificationException;
28 import java.util.Enumeration;
29 import java.util.Hashtable;
30 import java.util.Iterator;
31 import java.util.Map;
32 import java.util.NoSuchElementException;
33 import java.util.Set;
34 import java.util.concurrent.ConcurrentMap;
35 import java.util.concurrent.locks.ReentrantLock;
36
37
38
39
40
41
42
43
44 public final class ConcurrentHashMap<K, V> extends AbstractMap<K, V>
45 implements ConcurrentMap<K, V> {
46
47
48
49
50
51 static final int DEFAULT_INITIAL_CAPACITY = 16;
52
53
54
55
56
57 static final float DEFAULT_LOAD_FACTOR = 0.75f;
58
59
60
61
62
63 static final int DEFAULT_CONCURRENCY_LEVEL = 16;
64
65
66
67
68
69
70 static final int MAXIMUM_CAPACITY = 1 << 30;
71
72
73
74
75
76 static final int MAX_SEGMENTS = 1 << 16;
77
78
79
80
81
82
83
84 static final int RETRIES_BEFORE_LOCK = 2;
85
86
87
88
89
90
91
92 final int segmentMask;
93
94
95
96
97 final int segmentShift;
98
99
100
101
102 final Segment<K, V>[] segments;
103
104 Set<K> keySet;
105 Set<Map.Entry<K, V>> entrySet;
106 Collection<V> values;
107
108
109
110
111
112
113
114
115
116
117 private static int hash(int h) {
118
119
120 h += h << 15 ^ 0xffffcd7d;
121 h ^= h >>> 10;
122 h += h << 3;
123 h ^= h >>> 6;
124 h += (h << 2) + (h << 14);
125 return h ^ h >>> 16;
126 }
127
128
129
130
131
132
133
134 Segment<K, V> segmentFor(int hash) {
135 return segments[hash >>> segmentShift & segmentMask];
136 }
137
138 private static int hashOf(Object key) {
139 return hash(key.hashCode());
140 }
141
142
143
144
145
146
147
148
149
150
151
152
153
154 static final class HashEntry<K, V> {
155 final Object key;
156 final int hash;
157 volatile Object value;
158 final HashEntry<K, V> next;
159
160 HashEntry(
161 K key, int hash, HashEntry<K, V> next, V value) {
162 this.hash = hash;
163 this.next = next;
164 this.key = key;
165 this.value = value;
166 }
167
168 @SuppressWarnings("unchecked")
169 K key() {
170 return (K) key;
171 }
172
173 @SuppressWarnings("unchecked")
174 V value() {
175 return (V) value;
176 }
177
178 void setValue(V value) {
179 this.value = value;
180 }
181
182 @SuppressWarnings("unchecked")
183 static <K, V> HashEntry<K, V>[] newArray(int i) {
184 return new HashEntry[i];
185 }
186 }
187
188
189
190
191
192
193 static final class Segment<K, V> extends ReentrantLock {
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229 private static final long serialVersionUID = -2001752926705396395L;
230
231
232
233
234 transient volatile int count;
235
236
237
238
239
240
241
242
243 int modCount;
244
245
246
247
248
249 int threshold;
250
251
252
253
254 transient volatile HashEntry<K, V>[] table;
255
256
257
258
259
260
261 final float loadFactor;
262
263 Segment(int initialCapacity, float lf) {
264 loadFactor = lf;
265 setTable(HashEntry.<K, V>newArray(initialCapacity));
266 }
267
268 @SuppressWarnings("unchecked")
269 static <K, V> Segment<K, V>[] newArray(int i) {
270 return new Segment[i];
271 }
272
273 private static boolean keyEq(Object src, Object dest) {
274 return src.equals(dest);
275 }
276
277
278
279
280
281 void setTable(HashEntry<K, V>[] newTable) {
282 threshold = (int) (newTable.length * loadFactor);
283 table = newTable;
284 }
285
286
287
288
289 HashEntry<K, V> getFirst(int hash) {
290 HashEntry<K, V>[] tab = table;
291 return tab[hash & tab.length - 1];
292 }
293
294 HashEntry<K, V> newHashEntry(
295 K key, int hash, HashEntry<K, V> next, V value) {
296 return new HashEntry<K, V>(key, hash, next, value);
297 }
298
299
300
301
302
303
304
305 V readValueUnderLock(HashEntry<K, V> e) {
306 lock();
307 try {
308 return e.value();
309 } finally {
310 unlock();
311 }
312 }
313
314
315
316 V get(Object key, int hash) {
317 if (count != 0) {
318 HashEntry<K, V> e = getFirst(hash);
319 while (e != null) {
320 if (e.hash == hash && keyEq(key, e.key())) {
321 V opaque = e.value();
322 if (opaque != null) {
323 return opaque;
324 }
325
326 return readValueUnderLock(e);
327 }
328 e = e.next;
329 }
330 }
331 return null;
332 }
333
334 boolean containsKey(Object key, int hash) {
335 if (count != 0) {
336 HashEntry<K, V> e = getFirst(hash);
337 while (e != null) {
338 if (e.hash == hash && keyEq(key, e.key())) {
339 return true;
340 }
341 e = e.next;
342 }
343 }
344 return false;
345 }
346
347 boolean containsValue(Object value) {
348 if (count != 0) {
349 for (HashEntry<K, V> e: table) {
350 for (; e != null; e = e.next) {
351 V opaque = e.value();
352 V v;
353
354 if (opaque == null) {
355 v = readValueUnderLock(e);
356 } else {
357 v = opaque;
358 }
359
360 if (value.equals(v)) {
361 return true;
362 }
363 }
364 }
365 }
366 return false;
367 }
368
369 boolean replace(K key, int hash, V oldValue, V newValue) {
370 lock();
371 try {
372 HashEntry<K, V> e = getFirst(hash);
373 while (e != null && (e.hash != hash || !keyEq(key, e.key()))) {
374 e = e.next;
375 }
376
377 boolean replaced = false;
378 if (e != null && oldValue.equals(e.value())) {
379 replaced = true;
380 e.setValue(newValue);
381 }
382 return replaced;
383 } finally {
384 unlock();
385 }
386 }
387
388 V replace(K key, int hash, V newValue) {
389 lock();
390 try {
391 HashEntry<K, V> e = getFirst(hash);
392 while (e != null && (e.hash != hash || !keyEq(key, e.key()))) {
393 e = e.next;
394 }
395
396 V oldValue = null;
397 if (e != null) {
398 oldValue = e.value();
399 e.setValue(newValue);
400 }
401 return oldValue;
402 } finally {
403 unlock();
404 }
405 }
406
407 V put(K key, int hash, V value, boolean onlyIfAbsent) {
408 lock();
409 try {
410 int c = count;
411 if (c ++ > threshold) {
412 int reduced = rehash();
413 if (reduced > 0) {
414 count = (c -= reduced) - 1;
415 }
416 }
417
418 HashEntry<K, V>[] tab = table;
419 int index = hash & tab.length - 1;
420 HashEntry<K, V> first = tab[index];
421 HashEntry<K, V> e = first;
422 while (e != null && (e.hash != hash || !keyEq(key, e.key()))) {
423 e = e.next;
424 }
425
426 V oldValue;
427 if (e != null) {
428 oldValue = e.value();
429 if (!onlyIfAbsent) {
430 e.setValue(value);
431 }
432 } else {
433 oldValue = null;
434 ++ modCount;
435 tab[index] = newHashEntry(key, hash, first, value);
436 count = c;
437 }
438 return oldValue;
439 } finally {
440 unlock();
441 }
442 }
443
444 int rehash() {
445 HashEntry<K, V>[] oldTable = table;
446 int oldCapacity = oldTable.length;
447 if (oldCapacity >= MAXIMUM_CAPACITY) {
448 return 0;
449 }
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464 HashEntry<K, V>[] newTable = HashEntry.newArray(oldCapacity << 1);
465 threshold = (int) (newTable.length * loadFactor);
466 int sizeMask = newTable.length - 1;
467 int reduce = 0;
468 for (HashEntry<K, V> e: oldTable) {
469
470
471 if (e != null) {
472 HashEntry<K, V> next = e.next;
473 int idx = e.hash & sizeMask;
474
475
476 if (next == null) {
477 newTable[idx] = e;
478 } else {
479
480 HashEntry<K, V> lastRun = e;
481 int lastIdx = idx;
482 for (HashEntry<K, V> last = next; last != null; last = last.next) {
483 int k = last.hash & sizeMask;
484 if (k != lastIdx) {
485 lastIdx = k;
486 lastRun = last;
487 }
488 }
489 newTable[lastIdx] = lastRun;
490
491 for (HashEntry<K, V> p = e; p != lastRun; p = p.next) {
492
493 K key = p.key();
494 if (key == null) {
495 reduce++;
496 continue;
497 }
498 int k = p.hash & sizeMask;
499 HashEntry<K, V> n = newTable[k];
500 newTable[k] = newHashEntry(key, p.hash, n, p.value());
501 }
502 }
503 }
504 }
505 table = newTable;
506 return reduce;
507 }
508
509
510
511
512 V remove(Object key, int hash, Object value, boolean refRemove) {
513 lock();
514 try {
515 int c = count - 1;
516 HashEntry<K, V>[] tab = table;
517 int index = hash & tab.length - 1;
518 HashEntry<K, V> first = tab[index];
519 HashEntry<K, V> e = first;
520
521 while (e != null && key != e.key &&
522 (refRemove || hash != e.hash || !keyEq(key, e.key()))) {
523 e = e.next;
524 }
525
526 V oldValue = null;
527 if (e != null) {
528 V v = e.value();
529 if (value == null || value.equals(v)) {
530 oldValue = v;
531
532
533 ++ modCount;
534 HashEntry<K, V> newFirst = e.next;
535 for (HashEntry<K, V> p = first; p != e; p = p.next) {
536 K pKey = p.key();
537 if (pKey == null) {
538 c --;
539 continue;
540 }
541
542 newFirst = newHashEntry(
543 pKey, p.hash, newFirst, p.value());
544 }
545 tab[index] = newFirst;
546 count = c;
547 }
548 }
549 return oldValue;
550 } finally {
551 unlock();
552 }
553 }
554
555 void clear() {
556 if (count != 0) {
557 lock();
558 try {
559 HashEntry<K, V>[] tab = table;
560 for (int i = 0; i < tab.length; i ++) {
561 tab[i] = null;
562 }
563 ++ modCount;
564 count = 0;
565 } finally {
566 unlock();
567 }
568 }
569 }
570 }
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590 public ConcurrentHashMap(
591 int initialCapacity, float loadFactor,
592 int concurrencyLevel) {
593 if (!(loadFactor > 0) || initialCapacity < 0 || concurrencyLevel <= 0) {
594 throw new IllegalArgumentException();
595 }
596
597 if (concurrencyLevel > MAX_SEGMENTS) {
598 concurrencyLevel = MAX_SEGMENTS;
599 }
600
601
602 int sshift = 0;
603 int ssize = 1;
604 while (ssize < concurrencyLevel) {
605 ++ sshift;
606 ssize <<= 1;
607 }
608 segmentShift = 32 - sshift;
609 segmentMask = ssize - 1;
610 segments = Segment.newArray(ssize);
611
612 if (initialCapacity > MAXIMUM_CAPACITY) {
613 initialCapacity = MAXIMUM_CAPACITY;
614 }
615 int c = initialCapacity / ssize;
616 if (c * ssize < initialCapacity) {
617 ++ c;
618 }
619 int cap = 1;
620 while (cap < c) {
621 cap <<= 1;
622 }
623
624 for (int i = 0; i < segments.length; ++ i) {
625 segments[i] = new Segment<K, V>(cap, loadFactor);
626 }
627 }
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643 public ConcurrentHashMap(int initialCapacity, float loadFactor) {
644 this(initialCapacity, loadFactor, DEFAULT_CONCURRENCY_LEVEL);
645 }
646
647
648
649
650
651
652
653
654
655
656
657 public ConcurrentHashMap(int initialCapacity) {
658 this(initialCapacity, DEFAULT_LOAD_FACTOR, DEFAULT_CONCURRENCY_LEVEL);
659 }
660
661
662
663
664
665
666 public ConcurrentHashMap() {
667 this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR, DEFAULT_CONCURRENCY_LEVEL);
668 }
669
670
671
672
673
674
675
676
677
678 public ConcurrentHashMap(Map<? extends K, ? extends V> m) {
679 this(Math.max((int) (m.size() / DEFAULT_LOAD_FACTOR) + 1,
680 DEFAULT_INITIAL_CAPACITY), DEFAULT_LOAD_FACTOR,
681 DEFAULT_CONCURRENCY_LEVEL);
682 putAll(m);
683 }
684
685
686
687
688
689
690 @Override
691 public boolean isEmpty() {
692 final Segment<K, V>[] segments = this.segments;
693
694
695
696
697
698
699
700
701 int[] mc = new int[segments.length];
702 int mcsum = 0;
703 for (int i = 0; i < segments.length; ++ i) {
704 if (segments[i].count != 0) {
705 return false;
706 } else {
707 mcsum += mc[i] = segments[i].modCount;
708 }
709 }
710
711
712
713 if (mcsum != 0) {
714 for (int i = 0; i < segments.length; ++ i) {
715 if (segments[i].count != 0 || mc[i] != segments[i].modCount) {
716 return false;
717 }
718 }
719 }
720 return true;
721 }
722
723
724
725
726
727
728
729
730 @Override
731 public int size() {
732 final Segment<K, V>[] segments = this.segments;
733 long sum = 0;
734 long check = 0;
735 int[] mc = new int[segments.length];
736
737
738 for (int k = 0; k < RETRIES_BEFORE_LOCK; ++ k) {
739 check = 0;
740 sum = 0;
741 int mcsum = 0;
742 for (int i = 0; i < segments.length; ++ i) {
743 sum += segments[i].count;
744 mcsum += mc[i] = segments[i].modCount;
745 }
746 if (mcsum != 0) {
747 for (int i = 0; i < segments.length; ++ i) {
748 check += segments[i].count;
749 if (mc[i] != segments[i].modCount) {
750 check = -1;
751 break;
752 }
753 }
754 }
755 if (check == sum) {
756 break;
757 }
758 }
759 if (check != sum) {
760 sum = 0;
761 for (Segment<K, V> segment: segments) {
762 segment.lock();
763 }
764 for (Segment<K, V> segment: segments) {
765 sum += segment.count;
766 }
767 for (Segment<K, V> segment: segments) {
768 segment.unlock();
769 }
770 }
771 if (sum > Integer.MAX_VALUE) {
772 return Integer.MAX_VALUE;
773 } else {
774 return (int) sum;
775 }
776 }
777
778
779
780
781
782
783
784
785
786
787
788
789 @Override
790 public V get(Object key) {
791 int hash = hashOf(key);
792 return segmentFor(hash).get(key, hash);
793 }
794
795
796
797
798
799
800
801
802
803
804 @Override
805 public boolean containsKey(Object key) {
806 int hash = hashOf(key);
807 return segmentFor(hash).containsKey(key, hash);
808 }
809
810
811
812
813
814
815
816
817
818
819
820
821 @Override
822 public boolean containsValue(Object value) {
823 if (value == null) {
824 throw new NullPointerException();
825 }
826
827
828
829 final Segment<K, V>[] segments = this.segments;
830 int[] mc = new int[segments.length];
831
832
833 for (int k = 0; k < RETRIES_BEFORE_LOCK; ++ k) {
834 int mcsum = 0;
835 for (int i = 0; i < segments.length; ++ i) {
836 mcsum += mc[i] = segments[i].modCount;
837 if (segments[i].containsValue(value)) {
838 return true;
839 }
840 }
841 boolean cleanSweep = true;
842 if (mcsum != 0) {
843 for (int i = 0; i < segments.length; ++ i) {
844 if (mc[i] != segments[i].modCount) {
845 cleanSweep = false;
846 break;
847 }
848 }
849 }
850 if (cleanSweep) {
851 return false;
852 }
853 }
854
855 for (Segment<K, V> segment: segments) {
856 segment.lock();
857 }
858 boolean found = false;
859 try {
860 for (Segment<K, V> segment: segments) {
861 if (segment.containsValue(value)) {
862 found = true;
863 break;
864 }
865 }
866 } finally {
867 for (Segment<K, V> segment: segments) {
868 segment.unlock();
869 }
870 }
871 return found;
872 }
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887 public boolean contains(Object value) {
888 return containsValue(value);
889 }
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904 @Override
905 public V put(K key, V value) {
906 if (value == null) {
907 throw new NullPointerException();
908 }
909 int hash = hashOf(key);
910 return segmentFor(hash).put(key, hash, value, false);
911 }
912
913
914
915
916
917
918 public V putIfAbsent(K key, V value) {
919 if (value == null) {
920 throw new NullPointerException();
921 }
922 int hash = hashOf(key);
923 return segmentFor(hash).put(key, hash, value, true);
924 }
925
926
927
928
929
930
931
932
933 @Override
934 public void putAll(Map<? extends K, ? extends V> m) {
935 for (Map.Entry<? extends K, ? extends V> e: m.entrySet()) {
936 put(e.getKey(), e.getValue());
937 }
938 }
939
940
941
942
943
944
945
946
947
948
949 @Override
950 public V remove(Object key) {
951 int hash = hashOf(key);
952 return segmentFor(hash).remove(key, hash, null, false);
953 }
954
955
956
957
958 public boolean remove(Object key, Object value) {
959 int hash = hashOf(key);
960 if (value == null) {
961 return false;
962 }
963 return segmentFor(hash).remove(key, hash, value, false) != null;
964 }
965
966
967
968
969 public boolean replace(K key, V oldValue, V newValue) {
970 if (oldValue == null || newValue == null) {
971 throw new NullPointerException();
972 }
973 int hash = hashOf(key);
974 return segmentFor(hash).replace(key, hash, oldValue, newValue);
975 }
976
977
978
979
980
981
982 public V replace(K key, V value) {
983 if (value == null) {
984 throw new NullPointerException();
985 }
986 int hash = hashOf(key);
987 return segmentFor(hash).replace(key, hash, value);
988 }
989
990
991
992
993 @Override
994 public void clear() {
995 for (Segment<K, V> segment: segments) {
996 segment.clear();
997 }
998 }
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015 @Override
1016 public Set<K> keySet() {
1017 Set<K> ks = keySet;
1018 return ks != null? ks : (keySet = new KeySet());
1019 }
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036 @Override
1037 public Collection<V> values() {
1038 Collection<V> vs = values;
1039 return vs != null? vs : (values = new Values());
1040 }
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057 @Override
1058 public Set<Map.Entry<K, V>> entrySet() {
1059 Set<Map.Entry<K, V>> es = entrySet;
1060 return es != null? es : (entrySet = new EntrySet());
1061 }
1062
1063
1064
1065
1066
1067
1068
1069 public Enumeration<K> keys() {
1070 return new KeyIterator();
1071 }
1072
1073
1074
1075
1076
1077
1078
1079 public Enumeration<V> elements() {
1080 return new ValueIterator();
1081 }
1082
1083
1084
1085 abstract class HashIterator {
1086 int nextSegmentIndex;
1087 int nextTableIndex;
1088 HashEntry<K, V>[] currentTable;
1089 HashEntry<K, V> nextEntry;
1090 HashEntry<K, V> lastReturned;
1091 K currentKey;
1092
1093 HashIterator() {
1094 nextSegmentIndex = segments.length - 1;
1095 nextTableIndex = -1;
1096 advance();
1097 }
1098
1099 public void rewind() {
1100 nextSegmentIndex = segments.length - 1;
1101 nextTableIndex = -1;
1102 currentTable = null;
1103 nextEntry = null;
1104 lastReturned = null;
1105 currentKey = null;
1106 advance();
1107 }
1108
1109 public boolean hasMoreElements() {
1110 return hasNext();
1111 }
1112
1113 final void advance() {
1114 if (nextEntry != null && (nextEntry = nextEntry.next) != null) {
1115 return;
1116 }
1117
1118 while (nextTableIndex >= 0) {
1119 if ((nextEntry = currentTable[nextTableIndex --]) != null) {
1120 return;
1121 }
1122 }
1123
1124 while (nextSegmentIndex >= 0) {
1125 Segment<K, V> seg = segments[nextSegmentIndex --];
1126 if (seg.count != 0) {
1127 currentTable = seg.table;
1128 for (int j = currentTable.length - 1; j >= 0; -- j) {
1129 if ((nextEntry = currentTable[j]) != null) {
1130 nextTableIndex = j - 1;
1131 return;
1132 }
1133 }
1134 }
1135 }
1136 }
1137
1138 public boolean hasNext() {
1139 while (nextEntry != null) {
1140 if (nextEntry.key() != null) {
1141 return true;
1142 }
1143 advance();
1144 }
1145
1146 return false;
1147 }
1148
1149 HashEntry<K, V> nextEntry() {
1150 do {
1151 if (nextEntry == null) {
1152 throw new NoSuchElementException();
1153 }
1154
1155 lastReturned = nextEntry;
1156 currentKey = lastReturned.key();
1157 advance();
1158 } while (currentKey == null);
1159
1160 return lastReturned;
1161 }
1162
1163 public void remove() {
1164 if (lastReturned == null) {
1165 throw new IllegalStateException();
1166 }
1167 ConcurrentHashMap.this.remove(currentKey);
1168 lastReturned = null;
1169 }
1170 }
1171
1172 final class KeyIterator
1173 extends HashIterator implements ReusableIterator<K>, Enumeration<K> {
1174
1175 public K next() {
1176 return nextEntry().key();
1177 }
1178
1179 public K nextElement() {
1180 return nextEntry().key();
1181 }
1182 }
1183
1184 final class ValueIterator
1185 extends HashIterator implements ReusableIterator<V>, Enumeration<V> {
1186
1187 public V next() {
1188 return nextEntry().value();
1189 }
1190
1191 public V nextElement() {
1192 return nextEntry().value();
1193 }
1194 }
1195
1196
1197
1198
1199 static class SimpleEntry<K, V> implements Entry<K, V> {
1200
1201 private final K key;
1202
1203 private V value;
1204
1205 public SimpleEntry(K key, V value) {
1206 this.key = key;
1207 this.value = value;
1208 }
1209
1210 public SimpleEntry(Entry<? extends K, ? extends V> entry) {
1211 key = entry.getKey();
1212 value = entry.getValue();
1213 }
1214
1215 public K getKey() {
1216 return key;
1217 }
1218
1219 public V getValue() {
1220 return value;
1221 }
1222
1223 public V setValue(V value) {
1224 V oldValue = this.value;
1225 this.value = value;
1226 return oldValue;
1227 }
1228
1229 @Override
1230 public boolean equals(Object o) {
1231 if (!(o instanceof Map.Entry<?, ?>)) {
1232 return false;
1233 }
1234 @SuppressWarnings("rawtypes")
1235 Map.Entry e = (Map.Entry) o;
1236 return eq(key, e.getKey()) && eq(value, e.getValue());
1237 }
1238
1239 @Override
1240 public int hashCode() {
1241 return (key == null? 0 : key.hashCode()) ^ (value == null? 0 : value.hashCode());
1242 }
1243
1244 @Override
1245 public String toString() {
1246 return key + "=" + value;
1247 }
1248
1249 private static boolean eq(Object o1, Object o2) {
1250 return o1 == null? o2 == null : o1.equals(o2);
1251 }
1252 }
1253
1254
1255
1256
1257
1258 final class WriteThroughEntry extends SimpleEntry<K, V> {
1259
1260 WriteThroughEntry(K k, V v) {
1261 super(k, v);
1262 }
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272 @Override
1273 public V setValue(V value) {
1274
1275 if (value == null) {
1276 throw new NullPointerException();
1277 }
1278 V v = super.setValue(value);
1279 put(getKey(), value);
1280 return v;
1281 }
1282 }
1283
1284 final class EntryIterator extends HashIterator implements
1285 ReusableIterator<Entry<K, V>> {
1286 public Map.Entry<K, V> next() {
1287 HashEntry<K, V> e = nextEntry();
1288 return new WriteThroughEntry(e.key(), e.value());
1289 }
1290 }
1291
1292 final class KeySet extends AbstractSet<K> {
1293 @Override
1294 public Iterator<K> iterator() {
1295 return new KeyIterator();
1296 }
1297
1298 @Override
1299 public int size() {
1300 return ConcurrentHashMap.this.size();
1301 }
1302
1303 @Override
1304 public boolean isEmpty() {
1305 return ConcurrentHashMap.this.isEmpty();
1306 }
1307
1308 @Override
1309 public boolean contains(Object o) {
1310 return containsKey(o);
1311 }
1312
1313 @Override
1314 public boolean remove(Object o) {
1315 return ConcurrentHashMap.this.remove(o) != null;
1316 }
1317
1318 @Override
1319 public void clear() {
1320 ConcurrentHashMap.this.clear();
1321 }
1322 }
1323
1324 final class Values extends AbstractCollection<V> {
1325 @Override
1326 public Iterator<V> iterator() {
1327 return new ValueIterator();
1328 }
1329
1330 @Override
1331 public int size() {
1332 return ConcurrentHashMap.this.size();
1333 }
1334
1335 @Override
1336 public boolean isEmpty() {
1337 return ConcurrentHashMap.this.isEmpty();
1338 }
1339
1340 @Override
1341 public boolean contains(Object o) {
1342 return containsValue(o);
1343 }
1344
1345 @Override
1346 public void clear() {
1347 ConcurrentHashMap.this.clear();
1348 }
1349 }
1350
1351 final class EntrySet extends AbstractSet<Map.Entry<K, V>> {
1352 @Override
1353 public Iterator<Map.Entry<K, V>> iterator() {
1354 return new EntryIterator();
1355 }
1356
1357 @Override
1358 public boolean contains(Object o) {
1359 if (!(o instanceof Map.Entry<?, ?>)) {
1360 return false;
1361 }
1362 Map.Entry<?, ?> e = (Map.Entry<?, ?>) o;
1363 V v = get(e.getKey());
1364 return v != null && v.equals(e.getValue());
1365 }
1366
1367 @Override
1368 public boolean remove(Object o) {
1369 if (!(o instanceof Map.Entry<?, ?>)) {
1370 return false;
1371 }
1372 Map.Entry<?, ?> e = (Map.Entry<?, ?>) o;
1373 return ConcurrentHashMap.this.remove(e.getKey(), e.getValue());
1374 }
1375
1376 @Override
1377 public int size() {
1378 return ConcurrentHashMap.this.size();
1379 }
1380
1381 @Override
1382 public boolean isEmpty() {
1383 return ConcurrentHashMap.this.isEmpty();
1384 }
1385
1386 @Override
1387 public void clear() {
1388 ConcurrentHashMap.this.clear();
1389 }
1390 }
1391 }