1 package org.codehaus.plexus.util;
2
3
4
5
6
7
8
9 import java.io.IOException;
10 import java.io.ObjectInputStream;
11 import java.io.ObjectOutputStream;
12 import java.io.Serializable;
13 import java.util.AbstractCollection;
14 import java.util.AbstractSet;
15 import java.util.Collection;
16 import java.util.Iterator;
17 import java.util.Map;
18 import java.util.Set;
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56 public class FastMap<K, V> implements Map<K, V>, Cloneable, Serializable {
57
58
59
60
61 private transient EntryImpl[] _entries;
62
63
64
65
66 private transient int _capacity;
67
68
69
70
71 private transient int _mask;
72
73
74
75
76 private transient EntryImpl _poolFirst;
77
78
79
80
81 private transient EntryImpl _mapFirst;
82
83
84
85
86 private transient EntryImpl _mapLast;
87
88
89
90
91 private transient int _size;
92
93
94
95
96 public FastMap() {
97 initialize(256);
98 }
99
100
101
102
103
104
105
106
107
108
109
110
111
112 public FastMap(Map map) {
113 int capacity = (map instanceof FastMap) ? ((FastMap) map).capacity() : map.size();
114 initialize(capacity);
115 putAll(map);
116 }
117
118
119
120
121
122
123
124
125 public FastMap(int capacity) {
126 initialize(capacity);
127 }
128
129
130
131
132
133
134 @Override
135 public int size() {
136 return _size;
137 }
138
139
140
141
142
143
144
145 public int capacity() {
146 return _capacity;
147 }
148
149
150
151
152
153
154 @Override
155 public boolean isEmpty() {
156 return _size == 0;
157 }
158
159
160
161
162
163
164
165
166 @Override
167 public boolean containsKey(Object key) {
168 EntryImpl entry = _entries[keyHash(key) & _mask];
169 while (entry != null) {
170 if (key.equals(entry._key)) {
171 return true;
172 }
173 entry = entry._next;
174 }
175 return false;
176 }
177
178
179
180
181
182
183
184
185 @Override
186 public boolean containsValue(Object value) {
187 EntryImpl entry = _mapFirst;
188 while (entry != null) {
189 if (value.equals(entry._value)) {
190 return true;
191 }
192 entry = entry._after;
193 }
194 return false;
195 }
196
197
198
199
200
201
202
203
204
205 @Override
206 public V get(Object key) {
207 EntryImpl<K, V> entry = _entries[keyHash(key) & _mask];
208 while (entry != null) {
209 if (key.equals(entry._key)) {
210 return entry._value;
211 }
212 entry = entry._next;
213 }
214 return null;
215 }
216
217
218
219
220
221
222
223 public Map.Entry getEntry(Object key) {
224 EntryImpl entry = _entries[keyHash(key) & _mask];
225 while (entry != null) {
226 if (key.equals(entry._key)) {
227 return entry;
228 }
229 entry = entry._next;
230 }
231 return null;
232 }
233
234
235
236
237
238
239
240
241
242
243
244
245 @Override
246 public Object put(Object key, Object value) {
247 EntryImpl entry = _entries[keyHash(key) & _mask];
248 while (entry != null) {
249 if (key.equals(entry._key)) {
250 Object prevValue = entry._value;
251 entry._value = value;
252 return prevValue;
253 }
254 entry = entry._next;
255 }
256
257 addEntry(key, value);
258 return null;
259 }
260
261
262
263
264
265
266
267
268 @Override
269 public void putAll(Map<? extends K, ? extends V> map) {
270 for (Entry<? extends K, ? extends V> entry : map.entrySet()) {
271 addEntry(entry.getKey(), entry.getValue());
272 }
273 }
274
275
276
277
278
279
280
281
282
283
284 @Override
285 public V remove(Object key) {
286 EntryImpl<K, V> entry = _entries[keyHash(key) & _mask];
287 while (entry != null) {
288 if (key.equals(entry._key)) {
289 V prevValue = entry._value;
290 removeEntry(entry);
291 return prevValue;
292 }
293 entry = entry._next;
294 }
295 return null;
296 }
297
298
299
300
301 @Override
302 public void clear() {
303
304 for (EntryImpl entry = _mapFirst; entry != null; entry = entry._after) {
305 entry._key = null;
306 entry._value = null;
307 entry._before = null;
308 entry._next = null;
309 if (entry._previous == null) {
310 _entries[entry._index] = null;
311 } else {
312 entry._previous = null;
313 }
314 }
315
316
317 if (_mapLast != null) {
318 _mapLast._after = _poolFirst;
319 _poolFirst = _mapFirst;
320 _mapFirst = null;
321 _mapLast = null;
322 _size = 0;
323 sizeChanged();
324 }
325 }
326
327
328
329
330
331
332
333
334 public void setCapacity(int newCapacity) {
335 if (newCapacity > _capacity) {
336 for (int i = _capacity; i < newCapacity; i++) {
337 EntryImpl entry = new EntryImpl();
338 entry._after = _poolFirst;
339 _poolFirst = entry;
340 }
341 } else if (newCapacity < _capacity) {
342 for (int i = newCapacity; (i < _capacity) && (_poolFirst != null); i++) {
343
344 EntryImpl entry = _poolFirst;
345 _poolFirst = entry._after;
346 entry._after = null;
347 }
348 }
349
350 int tableLength = 16;
351 while (tableLength < newCapacity) {
352 tableLength <<= 1;
353 }
354
355 if (_entries.length != tableLength) {
356 _entries = new EntryImpl[tableLength];
357 _mask = tableLength - 1;
358
359
360 EntryImpl entry = _mapFirst;
361 while (entry != null) {
362 int index = keyHash(entry._key) & _mask;
363 entry._index = index;
364
365
366 entry._previous = null;
367 EntryImpl next = _entries[index];
368 entry._next = next;
369 if (next != null) {
370 next._previous = entry;
371 }
372 _entries[index] = entry;
373
374 entry = entry._after;
375 }
376 }
377 _capacity = newCapacity;
378 }
379
380
381
382
383
384
385 @Override
386 public Object clone() {
387 try {
388 FastMap clone = (FastMap) super.clone();
389 clone.initialize(_capacity);
390 clone.putAll(this);
391 return clone;
392 } catch (CloneNotSupportedException e) {
393
394 throw new InternalError();
395 }
396 }
397
398
399
400
401
402
403
404
405 @Override
406 public boolean equals(Object obj) {
407 if (obj == this) {
408 return true;
409 } else if (obj instanceof Map) {
410 Map that = (Map) obj;
411 if (this.size() == that.size()) {
412 EntryImpl entry = _mapFirst;
413 while (entry != null) {
414 if (!that.entrySet().contains(entry)) {
415 return false;
416 }
417 entry = entry._after;
418 }
419 return true;
420 } else {
421 return false;
422 }
423 } else {
424 return false;
425 }
426 }
427
428
429
430
431
432
433 @Override
434 public int hashCode() {
435 int code = 0;
436 EntryImpl entry = _mapFirst;
437 while (entry != null) {
438 code += entry.hashCode();
439 entry = entry._after;
440 }
441 return code;
442 }
443
444
445
446
447
448
449 @Override
450 public String toString() {
451 return entrySet().toString();
452 }
453
454
455
456
457
458
459
460
461
462
463 @Override
464 public Collection values() {
465 return _values;
466 }
467
468 private transient Values _values;
469
470 private class Values extends AbstractCollection {
471 @Override
472 public Iterator iterator() {
473 return new Iterator() {
474 EntryImpl after = _mapFirst;
475
476 EntryImpl before;
477
478 @Override
479 public void remove() {
480 removeEntry(before);
481 }
482
483 @Override
484 public boolean hasNext() {
485 return after != null;
486 }
487
488 @Override
489 public Object next() {
490 before = after;
491 after = after._after;
492 return before._value;
493 }
494 };
495 }
496
497 @Override
498 public int size() {
499 return _size;
500 }
501
502 @Override
503 public boolean contains(Object o) {
504 return containsValue(o);
505 }
506
507 @Override
508 public void clear() {
509 FastMap.this.clear();
510 }
511 }
512
513
514
515
516
517
518
519
520
521
522
523 @Override
524 public Set entrySet() {
525 return _entrySet;
526 }
527
528 private transient EntrySet _entrySet;
529
530 private class EntrySet extends AbstractSet {
531 @Override
532 public Iterator iterator() {
533 return new Iterator() {
534 EntryImpl after = _mapFirst;
535
536 EntryImpl before;
537
538 @Override
539 public void remove() {
540 removeEntry(before);
541 }
542
543 @Override
544 public boolean hasNext() {
545 return after != null;
546 }
547
548 @Override
549 public Object next() {
550 before = after;
551 after = after._after;
552 return before;
553 }
554 };
555 }
556
557 @Override
558 public int size() {
559 return _size;
560 }
561
562 @Override
563 public boolean contains(Object obj) {
564 if (obj instanceof Map.Entry) {
565 Map.Entry entry = (Map.Entry) obj;
566 Map.Entry mapEntry = getEntry(entry.getKey());
567 return entry.equals(mapEntry);
568 } else {
569 return false;
570 }
571 }
572
573 @Override
574 public boolean remove(Object obj) {
575 if (obj instanceof Map.Entry) {
576 Map.Entry entry = (Map.Entry) obj;
577 EntryImpl mapEntry = (EntryImpl) getEntry(entry.getKey());
578 if ((mapEntry != null) && (entry.getValue()).equals(mapEntry._value)) {
579 removeEntry(mapEntry);
580 return true;
581 }
582 }
583 return false;
584 }
585 }
586
587
588
589
590
591
592
593
594
595
596 @Override
597 public Set keySet() {
598 return _keySet;
599 }
600
601 private transient KeySet _keySet;
602
603 private class KeySet extends AbstractSet {
604 @Override
605 public Iterator iterator() {
606 return new Iterator() {
607 EntryImpl after = _mapFirst;
608
609 EntryImpl before;
610
611 @Override
612 public void remove() {
613 removeEntry(before);
614 }
615
616 @Override
617 public boolean hasNext() {
618 return after != null;
619 }
620
621 @Override
622 public Object next() {
623 before = after;
624 after = after._after;
625 return before._key;
626 }
627 };
628 }
629
630 @Override
631 public int size() {
632 return _size;
633 }
634
635 @Override
636 public boolean contains(Object obj) {
637 return FastMap.this.containsKey(obj);
638 }
639
640 @Override
641 public boolean remove(Object obj) {
642 return FastMap.this.remove(obj) != null;
643 }
644
645 @Override
646 public void clear() {
647 FastMap.this.clear();
648 }
649 }
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668 protected void sizeChanged() {
669 if (size() > capacity()) {
670 setCapacity(capacity() * 2);
671 }
672 }
673
674
675
676
677
678
679
680
681 private static int keyHash(Object key) {
682
683 int hashCode = key.hashCode();
684 hashCode += ~(hashCode << 9);
685 hashCode ^= (hashCode >>> 14);
686 hashCode += (hashCode << 4);
687 hashCode ^= (hashCode >>> 10);
688 return hashCode;
689 }
690
691
692
693
694
695
696
697 private void addEntry(Object key, Object value) {
698 EntryImpl entry = _poolFirst;
699 if (entry != null) {
700 _poolFirst = entry._after;
701 entry._after = null;
702 } else {
703 entry = new EntryImpl();
704 }
705
706
707 entry._key = key;
708 entry._value = value;
709 int index = keyHash(key) & _mask;
710 entry._index = index;
711
712
713 EntryImpl next = _entries[index];
714 entry._next = next;
715 if (next != null) {
716 next._previous = entry;
717 }
718 _entries[index] = entry;
719
720
721 if (_mapLast != null) {
722 entry._before = _mapLast;
723 _mapLast._after = entry;
724 } else {
725 _mapFirst = entry;
726 }
727 _mapLast = entry;
728
729
730 _size++;
731 sizeChanged();
732 }
733
734
735
736
737
738
739 private void removeEntry(EntryImpl entry) {
740
741
742 EntryImpl previous = entry._previous;
743 EntryImpl next = entry._next;
744 if (previous != null) {
745 previous._next = next;
746 entry._previous = null;
747 } else {
748 _entries[entry._index] = next;
749 }
750 if (next != null) {
751 next._previous = previous;
752 entry._next = null;
753 }
754
755
756 EntryImpl before = entry._before;
757 EntryImpl after = entry._after;
758 if (before != null) {
759 before._after = after;
760 entry._before = null;
761 } else {
762 _mapFirst = after;
763 }
764 if (after != null) {
765 after._before = before;
766 } else {
767 _mapLast = before;
768 }
769
770
771 entry._key = null;
772 entry._value = null;
773
774
775 entry._after = _poolFirst;
776 _poolFirst = entry;
777
778
779 _size--;
780 sizeChanged();
781 }
782
783
784
785
786
787
788
789 private void initialize(int capacity) {
790
791 int tableLength = 16;
792 while (tableLength < capacity) {
793 tableLength <<= 1;
794 }
795
796 _entries = new EntryImpl[tableLength];
797 _mask = tableLength - 1;
798 _capacity = capacity;
799 _size = 0;
800
801 _values = new Values();
802 _entrySet = new EntrySet();
803 _keySet = new KeySet();
804
805 _poolFirst = null;
806 _mapFirst = null;
807 _mapLast = null;
808
809 for (int i = 0; i < capacity; i++) {
810 EntryImpl entry = new EntryImpl();
811 entry._after = _poolFirst;
812 _poolFirst = entry;
813 }
814 }
815
816
817
818
819
820
821
822
823 private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
824 int capacity = stream.readInt();
825 initialize(capacity);
826 int size = stream.readInt();
827 for (int i = 0; i < size; i++) {
828 Object key = stream.readObject();
829 Object value = stream.readObject();
830 addEntry(key, value);
831 }
832 }
833
834
835
836
837
838
839
840 private void writeObject(ObjectOutputStream stream) throws IOException {
841 stream.writeInt(_capacity);
842 stream.writeInt(_size);
843 int count = 0;
844 EntryImpl entry = _mapFirst;
845 while (entry != null) {
846 stream.writeObject(entry._key);
847 stream.writeObject(entry._value);
848 count++;
849 entry = entry._after;
850 }
851 if (count != _size) {
852 throw new IOException("FastMap Corrupted");
853 }
854 }
855
856
857
858
859 private static final class EntryImpl<K, V> implements Map.Entry<K, V> {
860
861
862
863
864 private K _key;
865
866
867
868
869 private V _value;
870
871
872
873
874 private int _index;
875
876
877
878
879 private EntryImpl _previous;
880
881
882
883
884 private EntryImpl _next;
885
886
887
888
889 private EntryImpl _before;
890
891
892
893
894 private EntryImpl _after;
895
896
897
898
899
900
901 @Override
902 public K getKey() {
903 return _key;
904 }
905
906
907
908
909
910
911 @Override
912 public V getValue() {
913 return _value;
914 }
915
916
917
918
919
920
921
922 @Override
923 public V setValue(V value) {
924 V old = _value;
925 _value = value;
926 return old;
927 }
928
929
930
931
932
933
934
935 @Override
936 public boolean equals(Object that) {
937 if (that instanceof Map.Entry) {
938 Map.Entry entry = (Map.Entry) that;
939 return (_key.equals(entry.getKey()))
940 && ((_value != null) ? _value.equals(entry.getValue()) : (entry.getValue() == null));
941 } else {
942 return false;
943 }
944 }
945
946
947
948
949
950
951 @Override
952 public int hashCode() {
953 return _key.hashCode() ^ ((_value != null) ? _value.hashCode() : 0);
954 }
955
956
957
958
959
960
961 @Override
962 public String toString() {
963 return _key + "=" + _value;
964 }
965 }
966 }