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