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