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
644 public ConcurrentHashMap(int initialCapacity, float loadFactor) {
645 this(initialCapacity, loadFactor, DEFAULT_CONCURRENCY_LEVEL);
646 }
647
648
649
650
651
652
653
654
655
656
657
658 public ConcurrentHashMap(int initialCapacity) {
659 this(initialCapacity, DEFAULT_LOAD_FACTOR, DEFAULT_CONCURRENCY_LEVEL);
660 }
661
662
663
664
665
666
667 public ConcurrentHashMap() {
668 this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR, DEFAULT_CONCURRENCY_LEVEL);
669 }
670
671
672
673
674
675
676
677
678
679 public ConcurrentHashMap(Map<? extends K, ? extends V> m) {
680 this(Math.max((int) (m.size() / DEFAULT_LOAD_FACTOR) + 1,
681 DEFAULT_INITIAL_CAPACITY), DEFAULT_LOAD_FACTOR,
682 DEFAULT_CONCURRENCY_LEVEL);
683 putAll(m);
684 }
685
686
687
688
689
690
691 @Override
692 public boolean isEmpty() {
693 final Segment<K, V>[] segments = this.segments;
694
695
696
697
698
699
700
701
702 int[] mc = new int[segments.length];
703 int mcsum = 0;
704 for (int i = 0; i < segments.length; ++ i) {
705 if (segments[i].count != 0) {
706 return false;
707 } else {
708 mcsum += mc[i] = segments[i].modCount;
709 }
710 }
711
712
713
714 if (mcsum != 0) {
715 for (int i = 0; i < segments.length; ++ i) {
716 if (segments[i].count != 0 || mc[i] != segments[i].modCount) {
717 return false;
718 }
719 }
720 }
721 return true;
722 }
723
724
725
726
727
728
729
730
731 @Override
732 public int size() {
733 final Segment<K, V>[] segments = this.segments;
734 long sum = 0;
735 long check = 0;
736 int[] mc = new int[segments.length];
737
738
739 for (int k = 0; k < RETRIES_BEFORE_LOCK; ++ k) {
740 check = 0;
741 sum = 0;
742 int mcsum = 0;
743 for (int i = 0; i < segments.length; ++ i) {
744 sum += segments[i].count;
745 mcsum += mc[i] = segments[i].modCount;
746 }
747 if (mcsum != 0) {
748 for (int i = 0; i < segments.length; ++ i) {
749 check += segments[i].count;
750 if (mc[i] != segments[i].modCount) {
751 check = -1;
752 break;
753 }
754 }
755 }
756 if (check == sum) {
757 break;
758 }
759 }
760 if (check != sum) {
761 sum = 0;
762 for (Segment<K, V> segment: segments) {
763 segment.lock();
764 }
765 for (Segment<K, V> segment: segments) {
766 sum += segment.count;
767 }
768 for (Segment<K, V> segment: segments) {
769 segment.unlock();
770 }
771 }
772 if (sum > Integer.MAX_VALUE) {
773 return Integer.MAX_VALUE;
774 } else {
775 return (int) sum;
776 }
777 }
778
779
780
781
782
783
784
785
786
787
788
789
790 @Override
791 public V get(Object key) {
792 int hash = hashOf(key);
793 return segmentFor(hash).get(key, hash);
794 }
795
796
797
798
799
800
801
802
803
804
805 @Override
806 public boolean containsKey(Object key) {
807 int hash = hashOf(key);
808 return segmentFor(hash).containsKey(key, hash);
809 }
810
811
812
813
814
815
816
817
818
819
820
821
822 @Override
823 public boolean containsValue(Object value) {
824 if (value == null) {
825 throw new NullPointerException();
826 }
827
828
829
830 final Segment<K, V>[] segments = this.segments;
831 int[] mc = new int[segments.length];
832
833
834 for (int k = 0; k < RETRIES_BEFORE_LOCK; ++ k) {
835 int mcsum = 0;
836 for (int i = 0; i < segments.length; ++ i) {
837 mcsum += mc[i] = segments[i].modCount;
838 if (segments[i].containsValue(value)) {
839 return true;
840 }
841 }
842 boolean cleanSweep = true;
843 if (mcsum != 0) {
844 for (int i = 0; i < segments.length; ++ i) {
845 if (mc[i] != segments[i].modCount) {
846 cleanSweep = false;
847 break;
848 }
849 }
850 }
851 if (cleanSweep) {
852 return false;
853 }
854 }
855
856 for (Segment<K, V> segment: segments) {
857 segment.lock();
858 }
859 boolean found = false;
860 try {
861 for (Segment<K, V> segment: segments) {
862 if (segment.containsValue(value)) {
863 found = true;
864 break;
865 }
866 }
867 } finally {
868 for (Segment<K, V> segment: segments) {
869 segment.unlock();
870 }
871 }
872 return found;
873 }
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888 public boolean contains(Object value) {
889 return containsValue(value);
890 }
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905 @Override
906 public V put(K key, V value) {
907 if (value == null) {
908 throw new NullPointerException();
909 }
910 int hash = hashOf(key);
911 return segmentFor(hash).put(key, hash, value, false);
912 }
913
914
915
916
917
918
919 public V putIfAbsent(K key, V value) {
920 if (value == null) {
921 throw new NullPointerException();
922 }
923 int hash = hashOf(key);
924 return segmentFor(hash).put(key, hash, value, true);
925 }
926
927
928
929
930
931
932
933
934 @Override
935 public void putAll(Map<? extends K, ? extends V> m) {
936 for (Map.Entry<? extends K, ? extends V> e: m.entrySet()) {
937 put(e.getKey(), e.getValue());
938 }
939 }
940
941
942
943
944
945
946
947
948
949
950 @Override
951 public V remove(Object key) {
952 int hash = hashOf(key);
953 return segmentFor(hash).remove(key, hash, null, false);
954 }
955
956
957
958
959 public boolean remove(Object key, Object value) {
960 int hash = hashOf(key);
961 if (value == null) {
962 return false;
963 }
964 return segmentFor(hash).remove(key, hash, value, false) != null;
965 }
966
967
968
969
970 public boolean replace(K key, V oldValue, V newValue) {
971 if (oldValue == null || newValue == null) {
972 throw new NullPointerException();
973 }
974 int hash = hashOf(key);
975 return segmentFor(hash).replace(key, hash, oldValue, newValue);
976 }
977
978
979
980
981
982
983 public V replace(K key, V value) {
984 if (value == null) {
985 throw new NullPointerException();
986 }
987 int hash = hashOf(key);
988 return segmentFor(hash).replace(key, hash, value);
989 }
990
991
992
993
994 @Override
995 public void clear() {
996 for (Segment<K, V> segment: segments) {
997 segment.clear();
998 }
999 }
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016 @Override
1017 public Set<K> keySet() {
1018 Set<K> ks = keySet;
1019 return ks != null? ks : (keySet = new KeySet());
1020 }
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037 @Override
1038 public Collection<V> values() {
1039 Collection<V> vs = values;
1040 return vs != null? vs : (values = new Values());
1041 }
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058 @Override
1059 public Set<Map.Entry<K, V>> entrySet() {
1060 Set<Map.Entry<K, V>> es = entrySet;
1061 return es != null? es : (entrySet = new EntrySet());
1062 }
1063
1064
1065
1066
1067
1068
1069
1070 public Enumeration<K> keys() {
1071 return new KeyIterator();
1072 }
1073
1074
1075
1076
1077
1078
1079
1080 public Enumeration<V> elements() {
1081 return new ValueIterator();
1082 }
1083
1084
1085
1086 abstract class HashIterator {
1087 int nextSegmentIndex;
1088 int nextTableIndex;
1089 HashEntry<K, V>[] currentTable;
1090 HashEntry<K, V> nextEntry;
1091 HashEntry<K, V> lastReturned;
1092 K currentKey;
1093
1094 HashIterator() {
1095 nextSegmentIndex = segments.length - 1;
1096 nextTableIndex = -1;
1097 advance();
1098 }
1099
1100 public void rewind() {
1101 nextSegmentIndex = segments.length - 1;
1102 nextTableIndex = -1;
1103 currentTable = null;
1104 nextEntry = null;
1105 lastReturned = null;
1106 currentKey = null;
1107 advance();
1108 }
1109
1110 public boolean hasMoreElements() {
1111 return hasNext();
1112 }
1113
1114 final void advance() {
1115 if (nextEntry != null && (nextEntry = nextEntry.next) != null) {
1116 return;
1117 }
1118
1119 while (nextTableIndex >= 0) {
1120 if ((nextEntry = currentTable[nextTableIndex --]) != null) {
1121 return;
1122 }
1123 }
1124
1125 while (nextSegmentIndex >= 0) {
1126 Segment<K, V> seg = segments[nextSegmentIndex --];
1127 if (seg.count != 0) {
1128 currentTable = seg.table;
1129 for (int j = currentTable.length - 1; j >= 0; -- j) {
1130 if ((nextEntry = currentTable[j]) != null) {
1131 nextTableIndex = j - 1;
1132 return;
1133 }
1134 }
1135 }
1136 }
1137 }
1138
1139 public boolean hasNext() {
1140 while (nextEntry != null) {
1141 if (nextEntry.key() != null) {
1142 return true;
1143 }
1144 advance();
1145 }
1146
1147 return false;
1148 }
1149
1150 HashEntry<K, V> nextEntry() {
1151 do {
1152 if (nextEntry == null) {
1153 throw new NoSuchElementException();
1154 }
1155
1156 lastReturned = nextEntry;
1157 currentKey = lastReturned.key();
1158 advance();
1159 } while (currentKey == null);
1160
1161 return lastReturned;
1162 }
1163
1164 public void remove() {
1165 if (lastReturned == null) {
1166 throw new IllegalStateException();
1167 }
1168 ConcurrentHashMap.this.remove(currentKey);
1169 lastReturned = null;
1170 }
1171 }
1172
1173 final class KeyIterator
1174 extends HashIterator implements ReusableIterator<K>, Enumeration<K> {
1175
1176 public K next() {
1177 return nextEntry().key();
1178 }
1179
1180 public K nextElement() {
1181 return nextEntry().key();
1182 }
1183 }
1184
1185 final class ValueIterator
1186 extends HashIterator implements ReusableIterator<V>, Enumeration<V> {
1187
1188 public V next() {
1189 return nextEntry().value();
1190 }
1191
1192 public V nextElement() {
1193 return nextEntry().value();
1194 }
1195 }
1196
1197
1198
1199
1200 static class SimpleEntry<K, V> implements Entry<K, V> {
1201
1202 private final K key;
1203
1204 private V value;
1205
1206 public SimpleEntry(K key, V value) {
1207 this.key = key;
1208 this.value = value;
1209
1210 }
1211
1212 public SimpleEntry(Entry<? extends K, ? extends V> entry) {
1213 key = entry.getKey();
1214 value = entry.getValue();
1215
1216 }
1217
1218 public K getKey() {
1219 return key;
1220 }
1221
1222 public V getValue() {
1223 return value;
1224 }
1225
1226 public V setValue(V value) {
1227 V oldValue = this.value;
1228 this.value = value;
1229 return oldValue;
1230 }
1231
1232 @Override
1233 public boolean equals(Object o) {
1234 if (!(o instanceof Map.Entry<?, ?>)) {
1235 return false;
1236 }
1237 @SuppressWarnings("rawtypes")
1238 Map.Entry e = (Map.Entry) o;
1239 return eq(key, e.getKey()) && eq(value, e.getValue());
1240 }
1241
1242 @Override
1243 public int hashCode() {
1244 return (key == null? 0 : key.hashCode()) ^ (value == null? 0 : value.hashCode());
1245 }
1246
1247 @Override
1248 public String toString() {
1249 return key + "=" + value;
1250 }
1251
1252 private static boolean eq(Object o1, Object o2) {
1253 return o1 == null? o2 == null : o1.equals(o2);
1254 }
1255 }
1256
1257
1258
1259
1260
1261 final class WriteThroughEntry extends SimpleEntry<K, V> {
1262
1263 WriteThroughEntry(K k, V v) {
1264 super(k, v);
1265 }
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275 @Override
1276 public V setValue(V value) {
1277
1278 if (value == null) {
1279 throw new NullPointerException();
1280 }
1281 V v = super.setValue(value);
1282 put(getKey(), value);
1283 return v;
1284 }
1285
1286 }
1287
1288 final class EntryIterator extends HashIterator implements
1289 ReusableIterator<Entry<K, V>> {
1290 public Map.Entry<K, V> next() {
1291 HashEntry<K, V> e = nextEntry();
1292 return new WriteThroughEntry(e.key(), e.value());
1293 }
1294 }
1295
1296 final class KeySet extends AbstractSet<K> {
1297 @Override
1298 public Iterator<K> iterator() {
1299
1300 return new KeyIterator();
1301 }
1302
1303 @Override
1304 public int size() {
1305 return ConcurrentHashMap.this.size();
1306 }
1307
1308 @Override
1309 public boolean isEmpty() {
1310 return ConcurrentHashMap.this.isEmpty();
1311 }
1312
1313 @Override
1314 public boolean contains(Object o) {
1315 return containsKey(o);
1316 }
1317
1318 @Override
1319 public boolean remove(Object o) {
1320 return ConcurrentHashMap.this.remove(o) != null;
1321
1322 }
1323
1324 @Override
1325 public void clear() {
1326 ConcurrentHashMap.this.clear();
1327 }
1328 }
1329
1330 final class Values extends AbstractCollection<V> {
1331 @Override
1332 public Iterator<V> iterator() {
1333 return new ValueIterator();
1334 }
1335
1336 @Override
1337 public int size() {
1338 return ConcurrentHashMap.this.size();
1339 }
1340
1341 @Override
1342 public boolean isEmpty() {
1343 return ConcurrentHashMap.this.isEmpty();
1344 }
1345
1346 @Override
1347 public boolean contains(Object o) {
1348 return containsValue(o);
1349 }
1350
1351 @Override
1352 public void clear() {
1353 ConcurrentHashMap.this.clear();
1354 }
1355 }
1356
1357 final class EntrySet extends AbstractSet<Map.Entry<K, V>> {
1358 @Override
1359 public Iterator<Map.Entry<K, V>> iterator() {
1360 return new EntryIterator();
1361 }
1362
1363 @Override
1364 public boolean contains(Object o) {
1365 if (!(o instanceof Map.Entry<?, ?>)) {
1366 return false;
1367 }
1368 Map.Entry<?, ?> e = (Map.Entry<?, ?>) o;
1369 V v = get(e.getKey());
1370 return v != null && v.equals(e.getValue());
1371 }
1372
1373 @Override
1374 public boolean remove(Object o) {
1375 if (!(o instanceof Map.Entry<?, ?>)) {
1376 return false;
1377 }
1378 Map.Entry<?, ?> e = (Map.Entry<?, ?>) o;
1379 return ConcurrentHashMap.this.remove(e.getKey(), e.getValue());
1380 }
1381
1382 @Override
1383 public int size() {
1384 return ConcurrentHashMap.this.size();
1385 }
1386
1387 @Override
1388 public boolean isEmpty() {
1389 return ConcurrentHashMap.this.isEmpty();
1390 }
1391
1392 @Override
1393 public void clear() {
1394 ConcurrentHashMap.this.clear();
1395 }
1396 }
1397 }