1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package net.sf.eos.trie;
17
18 import java.io.Serializable;
19 import java.util.AbstractCollection;
20 import java.util.AbstractMap;
21 import java.util.AbstractSet;
22 import java.util.Collection;
23 import java.util.Comparator;
24 import java.util.ConcurrentModificationException;
25 import java.util.Iterator;
26 import java.util.Map;
27 import java.util.NoSuchElementException;
28 import java.util.Set;
29 import java.util.SortedMap;
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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96 public class PatriciaTrie<K, V> extends AbstractMap<K, V>
97 implements Trie<K, V>, Serializable {
98
99 private static final long serialVersionUID = 110232526181493307L;
100
101
102 private final TrieEntry<K, V> root = new TrieEntry<K, V>(null, null, -1);
103
104
105 private int size = 0;
106
107
108 private transient int modCount = 0;
109
110
111 private final KeyAnalyzer<? super K> keyAnalyzer;
112
113
114 public PatriciaTrie(KeyAnalyzer<? super K> keyAnalyzer) {
115 this.keyAnalyzer = keyAnalyzer;
116 }
117
118
119 public KeyAnalyzer<? super K> getKeyAnalyzer() {
120 return keyAnalyzer;
121 }
122
123
124 public Comparator<? super K> comparator() {
125 return keyAnalyzer;
126 }
127
128
129 @Override
130 public void clear() {
131 root.key = null;
132 root.bitIndex = -1;
133 root.value = null;
134
135 root.parent = null;
136 root.left = root;
137 root.right = null;
138 root.predecessor = root;
139
140 size = 0;
141 incrementModCount();
142 }
143
144
145 @Override
146 public boolean isEmpty() {
147 return size == 0;
148 }
149
150
151 @Override
152 public int size() {
153 return size;
154 }
155
156
157 private void incrementSize() {
158 size++;
159 incrementModCount();
160 }
161
162
163 private void decrementSize() {
164 size--;
165 incrementModCount();
166 }
167
168
169 private void incrementModCount() {
170 modCount++;
171 }
172
173
174
175
176
177
178 @Override
179 public V put(K key, V value) {
180 if (key == null) {
181 throw new NullPointerException("Key cannot be null");
182 }
183
184 int keyLength = length(key);
185
186
187
188 if (keyLength == 0) {
189 if (root.isEmpty()) {
190 incrementSize();
191 } else {
192 incrementModCount();
193 }
194 return root.setKeyValue(key, value);
195 }
196
197 TrieEntry<K, V> found = getNearestEntryForKey(key, keyLength);
198 if (key.equals(found.key)) {
199 if (found.isEmpty()) {
200 incrementSize();
201 } else {
202 incrementModCount();
203 }
204 return found.setKeyValue(key, value);
205 }
206
207 int bitIndex = bitIndex(key, found.key);
208 if (isValidBitIndex(bitIndex)) {
209
210 TrieEntry<K, V> t = new TrieEntry<K, V>(key, value, bitIndex);
211 addEntry(t, keyLength);
212 incrementSize();
213 return null;
214 } else if (isNullBitKey(bitIndex)) {
215
216
217
218
219 if (root.isEmpty()) {
220 incrementSize();
221 } else {
222 incrementModCount();
223 }
224 return root.setKeyValue(key, value);
225
226 } else if (isEqualBitKey(bitIndex)) {
227
228
229
230 if (found != root) {
231 incrementModCount();
232 return found.setKeyValue(key, value);
233 }
234 }
235
236 throw new IndexOutOfBoundsException("Failed to put: " + key
237 + " -> " + value
238 + ", " + bitIndex);
239 }
240
241
242 private TrieEntry<K, V> addEntry(TrieEntry<K, V> toAdd, int keyLength) {
243 TrieEntry<K, V> current = root.left;
244 TrieEntry<K, V> path = root;
245 while(true) {
246 if(current.bitIndex >= toAdd.bitIndex || current.bitIndex <= path.bitIndex) {
247 toAdd.predecessor = toAdd;
248
249 if (!isBitSet(toAdd.key, keyLength, toAdd.bitIndex)) {
250 toAdd.left = toAdd;
251 toAdd.right = current;
252 } else {
253 toAdd.left = current;
254 toAdd.right = toAdd;
255 }
256
257 toAdd.parent = path;
258 if (current.bitIndex >= toAdd.bitIndex) {
259 current.parent = toAdd;
260 }
261
262
263 if(current.bitIndex <= path.bitIndex) {
264 current.predecessor = toAdd;
265 }
266
267 if (path == root || !isBitSet(toAdd.key, keyLength, path.bitIndex))
268 path.left = toAdd;
269 else
270 path.right = toAdd;
271 return toAdd;
272 }
273
274 path = current;
275 if(!isBitSet(toAdd.key, keyLength, current.bitIndex))
276 current = current.left;
277 else
278 current = current.right;
279 }
280 }
281
282 @Override
283 public Set<Map.Entry<K,V>> entrySet() {
284 Set<Map.Entry<K,V>> es = entrySet;
285 return (es != null ? es : (entrySet = new EntrySet()));
286 }
287
288
289
290
291
292 @Override
293 public V get(Object k) {
294 TrieEntry<K, V> entry = getEntry(k);
295 return entry != null ? entry.getValue() : null;
296 }
297
298
299
300
301
302
303
304
305 TrieEntry<K,V> getEntry(Object k) {
306 K key = asKey(k);
307 if(key == null)
308 return null;
309
310 int keyLength = length(key);
311 TrieEntry<K,V> entry = getNearestEntryForKey(key, keyLength);
312 return !entry.isEmpty() && key.equals(entry.key) ? entry : null;
313 }
314
315
316 @SuppressWarnings("unchecked")
317 protected final K asKey(Object key) {
318 try {
319 return (K)key;
320 } catch(ClassCastException cce) {
321
322
323
324
325 return null;
326 }
327 }
328
329
330
331
332
333
334
335
336
337
338 private TrieEntry<K, V> getNearestEntryForKey(K key, int keyLength) {
339 TrieEntry<K, V> current = root.left;
340 TrieEntry<K, V> path = root;
341 while(true) {
342 if(current.bitIndex <= path.bitIndex)
343 return current;
344
345 path = current;
346 if(!isBitSet(key, keyLength, current.bitIndex))
347 current = current.left;
348 else
349 current = current.right;
350 }
351 }
352
353
354
355
356
357 @SuppressWarnings("unchecked")
358 public V select(K key) {
359 int keyLength = length(key);
360 TrieEntry[] result = new TrieEntry[1];
361 if (!selectR(root.left, -1, key, keyLength, result)) {
362 TrieEntry<K, V> e = result[0];
363 return e.getValue();
364 }
365 return null;
366 }
367
368
369
370
371
372
373 private boolean selectR(TrieEntry<K, V> h, int bitIndex,
374 final K key, final int keyLength, final TrieEntry[] result) {
375
376 if (h.bitIndex <= bitIndex) {
377
378
379
380 if (!h.isEmpty()) {
381 result[0] = h;
382 return false;
383 }
384 return true;
385 }
386
387 if (!isBitSet(key, keyLength, h.bitIndex)) {
388 if (selectR(h.left, h.bitIndex, key, keyLength, result)) {
389 return selectR(h.right, h.bitIndex, key, keyLength, result);
390 }
391 } else {
392 if (selectR(h.right, h.bitIndex, key, keyLength, result)) {
393 return selectR(h.left, h.bitIndex, key, keyLength, result);
394 }
395 }
396 return false;
397 }
398
399 @SuppressWarnings("unchecked")
400 public Map.Entry<K,V> select(K key, Cursor<? super K, ? super V> cursor) {
401 int keyLength = length(key);
402 TrieEntry[] result = new TrieEntry[]{ null };
403 selectR(root.left, -1, key, keyLength, cursor, result);
404 return result[0];
405 }
406
407 private boolean selectR(TrieEntry<K,V> h, int bitIndex,
408 final K key,
409 final int keyLength,
410 final Cursor<? super K, ? super V> cursor,
411 final TrieEntry[] result) {
412
413 if (h.bitIndex <= bitIndex) {
414 if(!h.isEmpty()) {
415 Cursor.SelectStatus ret = cursor.select(h);
416 switch(ret) {
417 case REMOVE:
418 throw new UnsupportedOperationException("cannot remove during select");
419 case EXIT:
420 result[0] = h;
421 return false;
422 case REMOVE_AND_EXIT:
423 TrieEntry<K, V> entry = new TrieEntry<K, V>(h.getKey(), h.getValue(), -1);
424 result[0] = entry;
425 removeEntry(h);
426 return false;
427 case CONTINUE:
428
429 }
430 }
431 return true;
432 }
433
434 if (!isBitSet(key, keyLength, h.bitIndex)) {
435 if (selectR(h.left, h.bitIndex, key, keyLength, cursor, result)) {
436 return selectR(h.right, h.bitIndex, key, keyLength, cursor, result);
437 }
438 } else {
439 if (selectR(h.right, h.bitIndex, key, keyLength, cursor, result)) {
440 return selectR(h.left, h.bitIndex, key, keyLength, cursor, result);
441 }
442 }
443
444 return false;
445 }
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469 public SortedMap<K, V> getPrefixedBy(K key) {
470 return getPrefixedByBits(key, 0, keyAnalyzer.length(key));
471 }
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498 public SortedMap<K, V> getPrefixedBy(K key, int length) {
499 return getPrefixedByBits(key, 0, length * keyAnalyzer.bitsPerElement());
500 }
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528 public SortedMap<K, V> getPrefixedBy(K key, int offset, int length) {
529 return getPrefixedByBits(key, offset * keyAnalyzer.bitsPerElement(), length * keyAnalyzer.bitsPerElement());
530 }
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555 public SortedMap<K, V> getPrefixedByBits(K key, int bitLength) {
556 return getPrefixedByBits(key, 0, bitLength);
557 }
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578 private SortedMap<K, V> getPrefixedByBits(K key, int offset, int length) {
579 int offsetLength = offset + length;
580 if (offsetLength > length(key)) {
581 throw new IllegalArgumentException(offset + " + " + length + " > " + length(key));
582 }
583
584 if(offsetLength == 0)
585 return this;
586
587 return new PrefixSubMap(key, offset, length);
588 }
589
590
591
592
593
594
595
596 @Override
597 public boolean containsKey(Object k) {
598 K key = asKey(k);
599 if(key == null)
600 return false;
601
602 int keyLength = length(key);
603 TrieEntry entry = getNearestEntryForKey(key, keyLength);
604 return !entry.isEmpty() && key.equals(entry.key);
605 }
606
607
608 @Override
609 public boolean containsValue(Object o) {
610 for(V v : values())
611 if(valEquals(v, o))
612 return true;
613 return false;
614 }
615
616
617
618
619
620
621
622
623
624 @Override
625 public V remove(Object k) {
626 K key = asKey(k);
627 if(key == null)
628 return null;
629
630 int keyLength = length(key);
631 TrieEntry<K, V> current = root.left;
632 TrieEntry<K, V> path = root;
633 while(true) {
634 if(current.bitIndex <= path.bitIndex) {
635 if(!current.isEmpty() && key.equals(current.key)) {
636 return removeEntry(current);
637 }
638 return null;
639 }
640
641 path = current;
642 if(!isBitSet(key, keyLength, current.bitIndex))
643 current = current.left;
644 else
645 current = current.right;
646 }
647 }
648
649
650
651
652
653
654
655
656 private V removeEntry(TrieEntry<K, V> h) {
657 if (h != root) {
658 if (h.isInternalNode()) {
659 removeInternalEntry(h);
660 } else {
661 removeExternalEntry(h);
662 }
663 }
664
665 decrementSize();
666 return h.setKeyValue(null, null);
667 }
668
669
670
671
672
673
674
675 private void removeExternalEntry(TrieEntry<K, V> h) {
676 if (h == root) {
677 throw new IllegalArgumentException("Cannot delete root Entry!");
678 } else if (!h.isExternalNode()) {
679 throw new IllegalArgumentException(h + " is not an external Entry!");
680 }
681
682 TrieEntry<K, V> parent = h.parent;
683 TrieEntry<K, V> child = (h.left == h) ? h.right : h.left;
684
685 if (parent.left == h) {
686 parent.left = child;
687 } else {
688 parent.right = child;
689 }
690
691
692 if (child.bitIndex > parent.bitIndex) {
693 child.parent = parent;
694 } else {
695 child.predecessor = parent;
696 }
697
698 }
699
700
701
702
703
704
705
706
707 private void removeInternalEntry(TrieEntry<K, V> h) {
708 if (h == root) {
709 throw new IllegalArgumentException("Cannot delete root Entry!");
710 } else if (!h.isInternalNode()) {
711 throw new IllegalArgumentException(h + " is not an internal Entry!");
712 }
713
714 TrieEntry<K, V> p = h.predecessor;
715
716
717 p.bitIndex = h.bitIndex;
718
719
720 {
721 TrieEntry<K, V> parent = p.parent;
722 TrieEntry<K, V> child = (p.left == h) ? p.right : p.left;
723
724
725
726
727
728
729
730 if(p.predecessor == p && p.parent != h)
731 p.predecessor = p.parent;
732
733 if (parent.left == p) {
734 parent.left = child;
735 } else {
736 parent.right = child;
737 }
738
739 if (child.bitIndex > parent.bitIndex) {
740 child.parent = parent;
741 }
742 };
743
744
745 {
746
747
748 if (h.left.parent == h) {
749 h.left.parent = p;
750 }
751
752 if (h.right.parent == h) {
753 h.right.parent = p;
754 }
755
756
757 if (h.parent.left == h) {
758 h.parent.left = p;
759 } else {
760 h.parent.right = p;
761 }
762 };
763
764
765
766 p.parent = h.parent;
767 p.left = h.left;
768 p.right = h.right;
769
770
771
772 if(isValidUplink(p.left, p))
773 p.left.predecessor = p;
774 if(isValidUplink(p.right, p))
775 p.right.predecessor = p;
776
777 }
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798 private TrieEntry<K, V> previousEntry(TrieEntry<K, V> start) {
799 if(start.predecessor == null)
800 throw new IllegalArgumentException("must have come from somewhere!");
801
802 if(start.predecessor.right == start) {
803 if(isValidUplink(start.predecessor.left, start.predecessor)) {
804 return start.predecessor.left;
805 }
806 return followRight(start.predecessor.left);
807 }
808 TrieEntry<K, V> node = start.predecessor;
809 while(node.parent != null && node == node.parent.left)
810 node = node.parent;
811 if(node.parent == null)
812 return null;
813 if(isValidUplink(node.parent.left, node.parent)) {
814 if(node.parent.left == root) {
815 if(root.isEmpty()) {
816 return null;
817 }
818 return root;
819 }
820 return node.parent.left;
821 }
822 return followRight(node.parent.left);
823 }
824
825
826
827
828
829 private TrieEntry<K, V> nextEntry(TrieEntry<K, V> node) {
830 if(node == null) {
831 return firstEntry();
832 }
833 return nextEntryImpl(node.predecessor, node, null);
834 }
835
836
837
838
839
840
841
842
843 private TrieEntry<K, V> nextEntryInSubtree(
844 final TrieEntry<K, V> node,
845 final TrieEntry<K, V> parentOfSubtree) {
846 if(node == null) {
847 return firstEntry();
848 }
849 return nextEntryImpl(node.predecessor, node, parentOfSubtree);
850 }
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885 private TrieEntry<K, V> nextEntryImpl(TrieEntry<K, V> start, TrieEntry<K, V> previous, TrieEntry<K, V> tree) {
886 TrieEntry<K, V> current = start;
887
888
889
890
891 if(previous == null || start != previous.predecessor) {
892 while(!current.left.isEmpty()) {
893
894
895 if(previous == current.left) {
896 break;
897 }
898
899 if(isValidUplink(current.left, current)) {
900 return current.left;
901 }
902
903 current = current.left;
904 }
905 }
906
907
908 if(current.isEmpty()) {
909 return null;
910 }
911
912
913
914
915
916
917
918
919
920
921 if(current.right == null)
922 return null;
923
924
925 if(previous != current.right) {
926
927 if(isValidUplink(current.right, current)) {
928 return current.right;
929 }
930
931
932 return nextEntryImpl(current.right, previous, tree);
933 }
934
935
936
937 while(current == current.parent.right) {
938
939 if(current == tree)
940 return null;
941
942 current = current.parent;
943 }
944
945
946 if(current == tree)
947 return null;
948
949
950
951 if(current.parent.right == null) {
952 return null;
953 }
954
955
956
957 if(previous != current.parent.right && isValidUplink(current.parent.right, current.parent)) {
958 return current.parent.right;
959 }
960
961
962 if(current.parent.right == current.parent) {
963 return null;
964 }
965
966
967 return nextEntryImpl(current.parent.right, previous, tree);
968 }
969
970
971 @Override
972 public String toString() {
973 StringBuilder buffer = new StringBuilder();
974 buffer.append("Trie[").append(size()).append("]={\n");
975 for(Iterator<Map.Entry<K, V>> i = newEntryIterator(); i.hasNext(); ) {
976 buffer.append(" ").append(i.next().toString()).append("\n");
977 }
978 buffer.append("}\n");
979 return buffer.toString();
980 }
981
982 public Map.Entry<K, V> traverse(Cursor<? super K, ? super V> cursor) {
983 TrieEntry<K, V> entry = nextEntry(null);
984 while(entry != null) {
985 TrieEntry<K, V> current = entry;
986 Cursor.SelectStatus ret = cursor.select(current);
987 entry = nextEntry(current);
988 switch(ret) {
989 case EXIT:
990 return current;
991 case REMOVE:
992 removeEntry(current);
993 break;
994 case REMOVE_AND_EXIT:
995 Map.Entry<K, V> value = new TrieEntry<K, V>(current.getKey(), current.getValue(), -1);
996 removeEntry(current);
997 return value;
998 case CONTINUE:
999 }
1000 }
1001
1002 return null;
1003 }
1004
1005
1006 private boolean isValidUplink(TrieEntry<K, V> next, TrieEntry<K, V> from) {
1007 return next != null && next.bitIndex <= from.bitIndex && !next.isEmpty();
1008 }
1009
1010
1011 private static boolean isValidBitIndex(int bitIndex) {
1012 return 0 <= bitIndex && bitIndex <= Integer.MAX_VALUE;
1013 }
1014
1015
1016 private static boolean isNullBitKey(int bitIndex) {
1017 return bitIndex == KeyAnalyzer.NULL_BIT_KEY;
1018 }
1019
1020
1021 private static boolean isEqualBitKey(int bitIndex) {
1022 return bitIndex == KeyAnalyzer.EQUAL_BIT_KEY;
1023 }
1024
1025
1026 private int length(K key) {
1027 if (key == null) {
1028 return 0;
1029 }
1030
1031 return keyAnalyzer.length(key);
1032 }
1033
1034
1035
1036
1037
1038 private boolean isBitSet(K key, int keyLength, int bitIndex) {
1039 if (key == null) {
1040 return false;
1041 }
1042 return keyAnalyzer.isBitSet(key, keyLength, bitIndex);
1043 }
1044
1045
1046
1047
1048
1049 private int bitIndex(K key, K foundKey) {
1050 return keyAnalyzer.bitIndex(key, 0, length(key), foundKey, 0, length(foundKey));
1051 }
1052
1053
1054 private static class TrieEntry<K,V> implements Map.Entry<K,V>, Serializable {
1055
1056 private static final long serialVersionUID = 4596023148184140013L;
1057
1058 private K key;
1059 private V value;
1060
1061
1062 private int bitIndex;
1063
1064
1065 private TrieEntry<K,V> parent;
1066
1067 private TrieEntry<K,V> left;
1068
1069 private TrieEntry<K,V> right;
1070
1071 private TrieEntry<K,V> predecessor;
1072
1073 private TrieEntry(K key, V value, int bitIndex) {
1074 this.key = key;
1075 this.value = value;
1076
1077 this.bitIndex = bitIndex;
1078
1079 this.parent = null;
1080 this.left = this;
1081 this.right = null;
1082 this.predecessor = this;
1083 }
1084
1085 @Override
1086 public boolean equals(Object o) {
1087 if(o == this) {
1088 return true;
1089 } else if(o instanceof Map.Entry) {
1090 Map.Entry e = (Map.Entry)o;
1091 Object k1 = getKey();
1092 Object k2 = e.getKey();
1093 if (k1 == k2 || (k1 != null && k1.equals(k2))) {
1094 Object v1 = getValue();
1095 Object v2 = e.getValue();
1096 if (v1 == v2 || (v1 != null && v1.equals(v2)))
1097 return true;
1098 }
1099 return false;
1100 } else {
1101 return false;
1102 }
1103 }
1104
1105
1106
1107
1108
1109
1110 public boolean isEmpty() {
1111 return key == null;
1112 }
1113
1114 public K getKey() {
1115 return key;
1116 }
1117
1118 public V getValue() {
1119 return value;
1120 }
1121
1122 public V setValue(V value) {
1123 V o = this.value;
1124 this.value = value;
1125 return o;
1126 }
1127
1128
1129
1130
1131
1132 private V setKeyValue(K key, V value) {
1133 this.key = key;
1134 return setValue(value);
1135 }
1136
1137
1138 private boolean isInternalNode() {
1139 return left != this && right != this;
1140 }
1141
1142
1143 private boolean isExternalNode() {
1144 return !isInternalNode();
1145 }
1146
1147 @Override
1148 public String toString() {
1149 StringBuilder buffer = new StringBuilder();
1150
1151 if (bitIndex == -1) {
1152 buffer.append("RootEntry(");
1153 } else {
1154 buffer.append("Entry(");
1155 }
1156
1157 buffer.append("key=").append(getKey()).append(" [").append(bitIndex).append("], ");
1158 buffer.append("value=").append(getValue()).append(", ");
1159
1160
1161 if (parent != null) {
1162 if (parent.bitIndex == -1) {
1163 buffer.append("parent=").append("ROOT");
1164 } else {
1165 buffer.append("parent=").append(parent.getKey()).append(" [").append(parent.bitIndex).append("]");
1166 }
1167 } else {
1168 buffer.append("parent=").append("null");
1169 }
1170 buffer.append(", ");
1171
1172 if (left != null) {
1173 if (left.bitIndex == -1) {
1174 buffer.append("left=").append("ROOT");
1175 } else {
1176 buffer.append("left=").append(left.getKey()).append(" [").append(left.bitIndex).append("]");
1177 }
1178 } else {
1179 buffer.append("left=").append("null");
1180 }
1181 buffer.append(", ");
1182
1183 if (right != null) {
1184 if (right.bitIndex == -1) {
1185 buffer.append("right=").append("ROOT");
1186 } else {
1187 buffer.append("right=").append(right.getKey()).append(" [").append(right.bitIndex).append("]");
1188 }
1189 } else {
1190 buffer.append("right=").append("null");
1191 }
1192 buffer.append(", ");
1193
1194 if(predecessor != null) {
1195 if(predecessor.bitIndex == -1) {
1196 buffer.append("predecessor=").append("ROOT");
1197 } else {
1198 buffer.append("predecessor=").append(predecessor.getKey()).append(" [").append(predecessor.bitIndex).append("]");
1199 }
1200 }
1201
1202 buffer.append(")");
1203 return buffer.toString();
1204 }
1205 }
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223 public static interface KeyAnalyzer<K> extends Comparator<K>, Serializable {
1224
1225
1226 public static final int NULL_BIT_KEY = -1;
1227
1228
1229
1230
1231
1232
1233 public static final int EQUAL_BIT_KEY = -2;
1234
1235
1236
1237
1238 public int length(K key);
1239
1240
1241 public boolean isBitSet(K key, int keyLength, int bitIndex);
1242
1243
1244
1245
1246
1247
1248
1249 public int bitIndex(K key, int keyStart, int keyLength,
1250 K found, int foundStart, int foundLength);
1251
1252
1253
1254
1255
1256 public int bitsPerElement();
1257
1258
1259
1260
1261
1262 public boolean isPrefix(K prefix, int offset, int length, K key);
1263 }
1264
1265
1266 private class SingletonIterator implements Iterator<Map.Entry<K, V>> {
1267 private final TrieEntry<K, V> entry;
1268 private int hit = 0;
1269
1270 public SingletonIterator(TrieEntry<K, V> entry) {
1271 this.entry = entry;
1272 }
1273
1274 public boolean hasNext() {
1275 return hit == 0;
1276 }
1277
1278 public Map.Entry<K, V> next() {
1279 if(hit != 0)
1280 throw new NoSuchElementException();
1281 hit++;
1282 return entry;
1283 }
1284
1285 public void remove() {
1286 if(hit != 1)
1287 throw new IllegalStateException();
1288 hit++;
1289 PatriciaTrie.this.removeEntry(entry);
1290 }
1291
1292 }
1293
1294
1295 private abstract class NodeIterator<E> implements Iterator<E> {
1296 protected int expectedModCount = modCount;
1297 protected TrieEntry<K, V> next;
1298 protected TrieEntry<K, V> current;
1299
1300
1301 protected NodeIterator() {
1302 next = PatriciaTrie.this.nextEntry(null);
1303 }
1304
1305
1306 protected NodeIterator(TrieEntry<K, V> firstEntry) {
1307 next = firstEntry;
1308 }
1309
1310 public boolean hasNext() {
1311 return next != null;
1312 }
1313
1314 TrieEntry<K,V> nextEntry() {
1315 if (modCount != expectedModCount)
1316 throw new ConcurrentModificationException();
1317 TrieEntry<K,V> e = next;
1318 if (e == null)
1319 throw new NoSuchElementException();
1320
1321 next = findNext(e);
1322 current = e;
1323 return e;
1324 }
1325
1326 protected TrieEntry<K, V> findNext(TrieEntry<K, V> prior) {
1327 return PatriciaTrie.this.nextEntry(prior);
1328 }
1329
1330 public void remove() {
1331 if (current == null)
1332 throw new IllegalStateException();
1333 if (modCount != expectedModCount)
1334 throw new ConcurrentModificationException();
1335
1336 TrieEntry<K, V> node = current;
1337 current = null;
1338 PatriciaTrie.this.removeEntry(node);
1339
1340 expectedModCount = modCount;
1341 }
1342 }
1343
1344 private class ValueIterator extends NodeIterator<V> {
1345 public V next() {
1346 return nextEntry().value;
1347 }
1348 }
1349
1350 private class KeyIterator extends NodeIterator<K> {
1351 public K next() {
1352 return nextEntry().getKey();
1353 }
1354 }
1355
1356 private class EntryIterator extends NodeIterator<Map.Entry<K,V>> {
1357 public Map.Entry<K,V> next() {
1358 return nextEntry();
1359 }
1360 }
1361
1362
1363 private class PrefixEntryIterator extends NodeIterator<Map.Entry<K, V>> {
1364
1365 protected final K prefix;
1366 protected final int offset;
1367 protected final int length;
1368 protected boolean lastOne;
1369
1370 protected TrieEntry<K, V> subtree;
1371
1372
1373 PrefixEntryIterator(TrieEntry<K, V> startScan, K prefix, int offset, int length) {
1374 subtree = startScan;
1375 next = PatriciaTrie.this.followLeft(startScan);
1376 this.prefix = prefix;
1377 this.offset = offset;
1378 this.length = length;
1379 }
1380
1381 public Map.Entry<K,V> next() {
1382 Map.Entry<K, V> entry = nextEntry();
1383 if(lastOne)
1384 next = null;
1385 return entry;
1386 }
1387
1388 @Override
1389 protected TrieEntry<K, V> findNext(TrieEntry<K, V> prior) {
1390 return PatriciaTrie.this.nextEntryInSubtree(prior, subtree);
1391 }
1392
1393 @Override
1394 public void remove() {
1395
1396
1397 boolean needsFixing = false;
1398 int bitIdx = subtree.bitIndex;
1399 if(current == subtree)
1400 needsFixing = true;
1401
1402 super.remove();
1403
1404
1405
1406 if(bitIdx != subtree.bitIndex || needsFixing)
1407 subtree = subtree(prefix, offset, length);
1408
1409
1410
1411
1412 if(length >= subtree.bitIndex)
1413 lastOne = true;
1414 }
1415
1416 }
1417
1418
1419 private class SubMapEntryIterator extends NodeIterator<Map.Entry<K,V>> {
1420 private final K firstExcludedKey;
1421
1422 SubMapEntryIterator(TrieEntry<K,V> first, TrieEntry<K,V> firstExcluded) {
1423 super(first);
1424 firstExcludedKey =
1425 (firstExcluded == null ? null : firstExcluded.key);
1426 }
1427
1428 @Override
1429 public boolean hasNext() {
1430 return next != null && next.key != firstExcludedKey;
1431 }
1432
1433 public Map.Entry<K,V> next() {
1434 if (next == null || next.key == firstExcludedKey)
1435 throw new NoSuchElementException();
1436 return nextEntry();
1437 }
1438 }
1439
1440 Iterator<K> newKeyIterator() {
1441 return new KeyIterator();
1442 }
1443
1444 Iterator<V> newValueIterator() {
1445 return new ValueIterator();
1446 }
1447
1448 Iterator<Map.Entry<K,V>> newEntryIterator() {
1449 return new EntryIterator();
1450 }
1451
1452
1453
1454
1455
1456
1457 private transient volatile Set<K> keySet = null;
1458 private transient volatile Collection<V> values = null;
1459 private transient volatile Set<Map.Entry<K,V>> entrySet = null;
1460
1461 private class EntrySet extends AbstractSet<Map.Entry<K,V>> {
1462 @Override
1463 public Iterator<Map.Entry<K,V>> iterator() {
1464 return newEntryIterator();
1465 }
1466
1467 @Override
1468 public boolean contains(Object o) {
1469 if (!(o instanceof Map.Entry))
1470 return false;
1471
1472 TrieEntry<K,V> candidate = getEntry(((Map.Entry)o).getKey());
1473 return candidate != null && candidate.equals(o);
1474 }
1475
1476 @Override
1477 public boolean remove(Object o) {
1478 int size = size();
1479 PatriciaTrie.this.remove(o);
1480 return size != size();
1481 }
1482
1483 @Override
1484 public int size() {
1485 return size;
1486 }
1487
1488 @Override
1489 public void clear() {
1490 PatriciaTrie.this.clear();
1491 }
1492 }
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505 @Override
1506 public Set<K> keySet() {
1507 Set<K> ks = keySet;
1508 return (ks != null ? ks : (keySet = new KeySet()));
1509 }
1510
1511 private class KeySet extends AbstractSet<K> {
1512 @Override
1513 public Iterator<K> iterator() {
1514 return newKeyIterator();
1515 }
1516 @Override
1517 public int size() {
1518 return size;
1519 }
1520 @Override
1521 public boolean contains(Object o) {
1522 return containsKey(o);
1523 }
1524 @Override
1525 public boolean remove(Object o) {
1526 int size = size();
1527 PatriciaTrie.this.remove(o);
1528 return size != size();
1529 }
1530 @Override
1531 public void clear() {
1532 PatriciaTrie.this.clear();
1533 }
1534 }
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547 @Override
1548 public Collection<V> values() {
1549 Collection<V> vs = values;
1550 return (vs != null ? vs : (values = new Values()));
1551 }
1552
1553
1554 private static boolean valEquals(Object o1, Object o2) {
1555 return (o1==null ? o2==null : o1.equals(o2));
1556 }
1557
1558 private class Values extends AbstractCollection<V> {
1559 @Override
1560 public Iterator<V> iterator() {
1561 return newValueIterator();
1562 }
1563 @Override
1564 public int size() {
1565 return size;
1566 }
1567 @Override
1568 public boolean contains(Object o) {
1569 return containsValue(o);
1570 }
1571 @Override
1572 public void clear() {
1573 PatriciaTrie.this.clear();
1574 }
1575 @Override
1576 public boolean remove(Object o) {
1577 for(Iterator<V> i = iterator(); i.hasNext(); ) {
1578 V v = i.next();
1579 if(valEquals(v, o)) {
1580 i.remove();
1581 return true;
1582 }
1583 }
1584 return false;
1585 }
1586 }
1587
1588
1589
1590
1591
1592
1593
1594 private TrieEntry<K, V> firstEntry() {
1595
1596 if(isEmpty())
1597 return null;
1598
1599 return followLeft(root);
1600 }
1601
1602
1603 private TrieEntry<K, V> followLeft(TrieEntry<K, V> node) {
1604 while(true) {
1605 TrieEntry<K, V> child = node.left;
1606
1607 if(child.isEmpty())
1608 child = node.right;
1609
1610 if(child.bitIndex <= node.bitIndex)
1611 return child;
1612
1613 node = child;
1614 }
1615 }
1616
1617
1618
1619
1620
1621
1622
1623 private TrieEntry<K, V> lastEntry() {
1624 return followRight(root.left);
1625 }
1626
1627
1628 protected TrieEntry<K, V> followRight(TrieEntry<K, V> node) {
1629
1630 if(node.right == null)
1631 return null;
1632
1633
1634 while(node.right.bitIndex > node.bitIndex)
1635 node = node.right;
1636
1637 return node.right;
1638 }
1639
1640 public K firstKey() {
1641 return firstEntry().getKey();
1642 }
1643
1644 public SortedMap<K, V> headMap(K toKey) {
1645 return new SubMap(null, toKey);
1646 }
1647
1648 public K lastKey() {
1649 TrieEntry<K, V> entry = lastEntry();
1650 if(entry != null) {
1651 return entry.getKey();
1652 }
1653 return null;
1654 }
1655
1656
1657 public SortedMap<K, V> subMap(K fromKey, K toKey) {
1658 return new SubMap(fromKey, toKey);
1659 }
1660
1661 public SortedMap<K, V> tailMap(K fromKey) {
1662 return new SubMap(fromKey, null);
1663 }
1664
1665
1666
1667
1668
1669 protected TrieEntry<K,V> higherEntry(K key) {
1670
1671
1672
1673 int keyLength = length(key);
1674
1675 if (keyLength == 0) {
1676 if(!root.isEmpty()) {
1677
1678 if(size() > 1) {
1679 return nextEntry(root);
1680 } else {
1681 return null;
1682 }
1683 } else {
1684
1685 return firstEntry();
1686 }
1687 }
1688
1689 TrieEntry<K, V> found = getNearestEntryForKey(key, keyLength);
1690 if (key.equals(found.key))
1691 return nextEntry(found);
1692
1693 int bitIndex = bitIndex(key, found.key);
1694 if (isValidBitIndex(bitIndex)) {
1695 TrieEntry<K, V> added = new TrieEntry<K, V>(key, null, bitIndex);
1696 addEntry(added, keyLength);
1697 incrementSize();
1698 TrieEntry<K, V> ceil = nextEntry(added);
1699 removeEntry(added);
1700 modCount -= 2;
1701 return ceil;
1702 } else if (isNullBitKey(bitIndex)) {
1703 if (!root.isEmpty())
1704 return firstEntry();
1705 else if(size() > 1)
1706 return nextEntry(firstEntry());
1707 else
1708 return null;
1709 } else if (isEqualBitKey(bitIndex)) {
1710 return nextEntry(found);
1711 }
1712
1713
1714 throw new IllegalStateException("invalid lookup: " + key);
1715 }
1716
1717
1718
1719
1720
1721 protected TrieEntry<K,V> ceilingEntry(K key) {
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740 int keyLength = length(key);
1741
1742 if (keyLength == 0) {
1743 if(!root.isEmpty())
1744 return root;
1745 else
1746 return firstEntry();
1747 }
1748
1749 TrieEntry<K, V> found = getNearestEntryForKey(key, keyLength);
1750 if (key.equals(found.key))
1751 return found;
1752
1753 int bitIndex = bitIndex(key, found.key);
1754 if (isValidBitIndex(bitIndex)) {
1755 TrieEntry<K, V> added = new TrieEntry<K, V>(key, null, bitIndex);
1756 addEntry(added, keyLength);
1757 incrementSize();
1758 TrieEntry<K, V> ceil = nextEntry(added);
1759 removeEntry(added);
1760 modCount -= 2;
1761 return ceil;
1762 } else if (isNullBitKey(bitIndex)) {
1763 if (!root.isEmpty())
1764 return root;
1765 else
1766 return firstEntry();
1767 } else if (isEqualBitKey(bitIndex)) {
1768 return found;
1769 }
1770
1771
1772 throw new IllegalStateException("invalid lookup: " + key);
1773 }
1774
1775
1776
1777
1778
1779 protected TrieEntry<K,V> lowerEntry(K key) {
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797 int keyLength = length(key);
1798
1799 if (keyLength == 0) {
1800 return null;
1801 }
1802
1803 TrieEntry<K, V> found = getNearestEntryForKey(key, keyLength);
1804 if (key.equals(found.key))
1805 return previousEntry(found);
1806
1807 int bitIndex = bitIndex(key, found.key);
1808 if (isValidBitIndex(bitIndex)) {
1809 TrieEntry<K, V> added = new TrieEntry<K, V>(key, null, bitIndex);
1810 addEntry(added, keyLength);
1811 incrementSize();
1812 TrieEntry<K, V> prior = previousEntry(added);
1813 removeEntry(added);
1814 modCount -= 2;
1815 return prior;
1816 } else if (isNullBitKey(bitIndex)) {
1817 return null;
1818 } else if (isEqualBitKey(bitIndex)) {
1819 return previousEntry(found);
1820 }
1821
1822
1823 throw new IllegalStateException("invalid lookup: " + key);
1824 }
1825
1826
1827
1828
1829
1830 protected TrieEntry<K,V> floorEntry(K key) {
1831
1832
1833
1834 int keyLength = length(key);
1835
1836 if (keyLength == 0) {
1837 if(!root.isEmpty())
1838 return root;
1839 else
1840 return null;
1841 }
1842
1843 TrieEntry<K, V> found = getNearestEntryForKey(key, keyLength);
1844 if (key.equals(found.key))
1845 return found;
1846
1847 int bitIndex = bitIndex(key, found.key);
1848 if (isValidBitIndex(bitIndex)) {
1849 TrieEntry<K, V> added = new TrieEntry<K, V>(key, null, bitIndex);
1850 addEntry(added, keyLength);
1851 incrementSize();
1852 TrieEntry<K, V> floor = previousEntry(added);
1853 removeEntry(added);
1854 modCount -= 2;
1855 return floor;
1856 } else if (isNullBitKey(bitIndex)) {
1857 if (!root.isEmpty())
1858 return root;
1859 else
1860 return null;
1861 } else if (isEqualBitKey(bitIndex)) {
1862 return found;
1863 }
1864
1865
1866 throw new IllegalStateException("invalid lookup: " + key);
1867 }
1868
1869
1870
1871
1872
1873
1874
1875
1876 private TrieEntry<K, V> subtree(K prefix, int offset, int length) {
1877 TrieEntry<K, V> current = root.left;
1878 TrieEntry<K, V> path = root;
1879 while(true) {
1880 if(current.bitIndex <= path.bitIndex || length < current.bitIndex)
1881 break;
1882
1883 path = current;
1884 if(!isBitSet(prefix, length+offset, current.bitIndex+offset)) {
1885 current = current.left;
1886 } else {
1887 current = current.right;
1888 }
1889 }
1890
1891
1892 TrieEntry<K, V> entry = current.isEmpty() ? path : current;
1893
1894
1895 if (entry.isEmpty())
1896 return null;
1897
1898 int offsetLength = offset + length;
1899
1900
1901
1902
1903
1904 if(entry == root && length(entry.getKey()) < offsetLength)
1905 return null;
1906
1907
1908
1909 if(isBitSet(prefix, offsetLength, offsetLength) !=
1910 isBitSet(entry.key, length(entry.key), length)) {
1911 return null;
1912 }
1913
1914
1915 int bitIndex = keyAnalyzer.bitIndex(prefix, offset, length,
1916 entry.key, 0, length(entry.getKey()));
1917 if (bitIndex >= 0 && bitIndex < length)
1918 return null;
1919
1920 return entry;
1921 }
1922
1923
1924 private class PrefixSubMap extends SubMap {
1925 protected final K prefix;
1926 protected final int offset;
1927 protected final int length;
1928 private transient int keyModCount = 0;
1929 protected int size;
1930
1931 PrefixSubMap(K prefix, int offset, int length) {
1932 this.prefix = prefix;
1933 this.offset = offset;
1934 this.length = length;
1935 fromInclusive = false;
1936 }
1937
1938 @Override
1939 public K firstKey() {
1940 fixup();
1941 TrieEntry<K,V> e;
1942 if(fromKey == null) {
1943 e = firstEntry();
1944 } else {
1945 e = higherEntry(fromKey);
1946 }
1947
1948 K first = e != null ? e.getKey() : null;
1949 if (e == null || !keyAnalyzer.isPrefix(prefix, offset, length, first))
1950 throw new NoSuchElementException();
1951 return first;
1952 }
1953
1954 @Override
1955 public K lastKey() {
1956 fixup();
1957 TrieEntry<K,V> e;
1958 if(toKey == null) {
1959 e = lastEntry();
1960 } else {
1961 e = lowerEntry(toKey);
1962 }
1963
1964 K last = e != null ? e.getKey() : null;
1965 if (e == null || !keyAnalyzer.isPrefix(prefix, offset, length, last))
1966 throw new NoSuchElementException();
1967 return last;
1968 }
1969
1970 @Override
1971 protected boolean inRange(K key) {
1972 return keyAnalyzer.isPrefix(prefix, offset, length, key);
1973 }
1974
1975 @Override
1976 protected boolean inRange2(K key) {
1977 return keyAnalyzer.isPrefix(prefix, offset, length, key);
1978 }
1979
1980 @Override
1981 protected boolean inToRange(K key, boolean forceInclusive) {
1982 return keyAnalyzer.isPrefix(prefix, offset, length, key);
1983 }
1984
1985 @Override
1986 protected boolean inFromRange(K key, boolean forceInclusive) {
1987 return keyAnalyzer.isPrefix(prefix, offset, length, key);
1988 }
1989
1990 private void fixup() {
1991
1992
1993 if(modCount != keyModCount) {
1994 Iterator<Map.Entry<K, V>> iter = entrySet().iterator();
1995 size = 0;
1996
1997 Map.Entry<K, V> entry = null;
1998 if(iter.hasNext()) {
1999 entry = iter.next();
2000 size = 1;
2001 }
2002
2003 fromKey = entry == null ? null : entry.getKey();
2004 if(fromKey != null) {
2005 TrieEntry<K, V> prior = previousEntry((TrieEntry<K, V>)entry);
2006 fromKey = prior == null ? null : prior.getKey();
2007 }
2008
2009 toKey = fromKey;
2010
2011 while(iter.hasNext()) {
2012 size++;
2013 entry = iter.next();
2014 }
2015
2016 toKey = entry == null ? null : entry.getKey();
2017
2018 if(toKey != null) {
2019 entry = nextEntry((TrieEntry<K, V>)entry);
2020 toKey = entry == null ? null : entry.getKey();
2021 }
2022
2023 keyModCount = modCount;
2024 }
2025 }
2026
2027 @Override
2028 protected Set<Map.Entry<K, V>> newSubMapEntrySet() {
2029 return new PrefixEntrySetView();
2030 }
2031
2032 private class PrefixEntrySetView extends SubMap.EntrySetView {
2033 private TrieEntry<K, V> prefixStart;
2034 private int iterModCount = 0;
2035
2036 @Override
2037 public int size() {
2038 fixup();
2039 return PrefixSubMap.this.size;
2040 }
2041
2042 @Override
2043 public Iterator<Map.Entry<K,V>> iterator() {
2044 if(modCount != iterModCount) {
2045 prefixStart = subtree(prefix, offset, length);
2046 iterModCount = modCount;
2047 }
2048
2049 if(prefixStart == null) {
2050 return EmptyIterator.emptyIterator();
2051 } else if(length >= prefixStart.bitIndex){
2052 return new SingletonIterator(prefixStart);
2053 } else {
2054 return new PrefixEntryIterator(prefixStart, prefix, offset, length);
2055 }
2056 }
2057 }
2058 }
2059
2060 private class SubMap extends AbstractMap<K,V> implements SortedMap<K,V>, java.io.Serializable {
2061
2062
2063
2064
2065 protected K fromKey;
2066
2067
2068 protected K toKey;
2069
2070
2071 protected boolean fromInclusive;
2072
2073
2074 protected boolean toInclusive;
2075
2076
2077
2078
2079
2080
2081 protected SubMap() {}
2082
2083 SubMap(K fromKey, K toKey) {
2084 if(fromKey == null && toKey == null)
2085 throw new IllegalArgumentException("must have a from or to!");
2086 if(fromKey != null && toKey != null && keyAnalyzer.compare(fromKey, toKey) > 0)
2087 throw new IllegalArgumentException("fromKey > toKey");
2088 this.fromKey = fromKey;
2089 this.toKey = toKey;
2090 fromInclusive = true;
2091 }
2092
2093 @Override
2094 public boolean isEmpty() {
2095 return entrySet().isEmpty();
2096 }
2097
2098 @SuppressWarnings("unchecked")
2099 @Override
2100 public boolean containsKey(Object key) {
2101 return inRange((K) key) && PatriciaTrie.this.containsKey(key);
2102 }
2103
2104 @SuppressWarnings("unchecked")
2105 @Override
2106 public V remove(Object key) {
2107 if(!inRange((K)key))
2108 return null;
2109 return PatriciaTrie.this.remove(key);
2110 }
2111
2112 @SuppressWarnings("unchecked")
2113 @Override
2114 public V get(Object key) {
2115 if (!inRange((K) key))
2116 return null;
2117 return PatriciaTrie.this.get(key);
2118 }
2119
2120 @Override
2121 public V put(K key, V value) {
2122 if (!inRange(key))
2123 throw new IllegalArgumentException("key out of range");
2124 return PatriciaTrie.this.put(key, value);
2125 }
2126
2127 public Comparator<? super K> comparator() {
2128 return keyAnalyzer;
2129 }
2130
2131 public K firstKey() {
2132 TrieEntry<K,V> e;
2133 if(fromKey == null) {
2134 e = firstEntry();
2135 } else {
2136 if(fromInclusive)
2137 e = ceilingEntry(fromKey);
2138 else
2139 e = higherEntry(fromKey);
2140 }
2141
2142 K first = e != null ? e.getKey() : null;
2143 if (e == null || toKey != null && !inToRange(first, false))
2144 throw new NoSuchElementException();
2145 return first;
2146 }
2147
2148 public K lastKey() {
2149 TrieEntry<K,V> e;
2150 if(toKey == null) {
2151 e = lastEntry();
2152 } else {
2153 if(toInclusive)
2154 e = floorEntry(toKey);
2155 else
2156 e = lowerEntry(toKey);
2157 }
2158
2159 K last = e != null ? e.getKey() : null;
2160 if (e == null || fromKey != null && !inFromRange(last, false))
2161 throw new NoSuchElementException();
2162 return last;
2163 }
2164
2165 private transient Set<Map.Entry<K,V>> entrySet;
2166
2167 @Override
2168 public Set<Map.Entry<K,V>> entrySet() {
2169 if(entrySet == null)
2170 entrySet = newSubMapEntrySet();
2171 return entrySet;
2172 }
2173
2174 protected Set<Map.Entry<K, V>> newSubMapEntrySet() {
2175 return new EntrySetView();
2176 }
2177
2178 class EntrySetView extends AbstractSet<Map.Entry<K,V>> {
2179 private transient int size = -1, sizeModCount;
2180
2181 @Override
2182 public int size() {
2183 if (size == -1 || sizeModCount != PatriciaTrie.this.modCount) {
2184 size = 0; sizeModCount = PatriciaTrie.this.modCount;
2185 Iterator i = iterator();
2186 while (i.hasNext()) {
2187 size++;
2188 i.next();
2189 }
2190 }
2191 return size;
2192 }
2193
2194 @Override
2195 public boolean isEmpty() {
2196 return !iterator().hasNext();
2197 }
2198
2199 @SuppressWarnings("unchecked")
2200 @Override
2201 public boolean contains(Object o) {
2202 if (!(o instanceof Map.Entry))
2203 return false;
2204 Map.Entry<K,V> entry = (Map.Entry<K,V>) o;
2205 K key = entry.getKey();
2206 if (!inRange(key))
2207 return false;
2208 TrieEntry<K, V> node = getEntry(key);
2209 return node != null &&
2210 valEquals(node.getValue(), entry.getValue());
2211 }
2212
2213 @SuppressWarnings("unchecked")
2214 @Override
2215 public boolean remove(Object o) {
2216 if (!(o instanceof Map.Entry))
2217 return false;
2218 Map.Entry<K,V> entry = (Map.Entry<K,V>) o;
2219 K key = entry.getKey();
2220 if (!inRange(key))
2221 return false;
2222 TrieEntry<K,V> node = getEntry(key);
2223 if (node!=null && valEquals(node.getValue(),entry.getValue())){
2224 removeEntry(node);
2225 return true;
2226 }
2227 return false;
2228 }
2229
2230 @Override
2231 public Iterator<Map.Entry<K,V>> iterator() {
2232 return new SubMapEntryIterator(
2233 (fromKey == null ? firstEntry() : ceilingEntry(fromKey)),
2234 (toKey == null ? null : ceilingEntry(toKey)));
2235 }
2236 }
2237
2238 public SortedMap<K,V> subMap(K fromKey, K toKey) {
2239 if (!inRange2(fromKey))
2240 throw new IllegalArgumentException("fromKey out of range");
2241 if (!inRange2(toKey))
2242 throw new IllegalArgumentException("toKey out of range");
2243 return new SubMap(fromKey, toKey);
2244 }
2245
2246 public SortedMap<K,V> headMap(K toKey) {
2247 if (!inRange2(toKey))
2248 throw new IllegalArgumentException("toKey out of range");
2249 return new SubMap(fromKey, toKey);
2250 }
2251
2252 public SortedMap<K,V> tailMap(K fromKey) {
2253 if (!inRange2(fromKey))
2254 throw new IllegalArgumentException("fromKey out of range");
2255 return new SubMap(fromKey, toKey);
2256 }
2257
2258 protected boolean inRange(K key) {
2259 return (fromKey == null || inFromRange(key, false)) &&
2260 (toKey == null || inToRange(key, false));
2261 }
2262
2263
2264 protected boolean inRange2(K key) {
2265 return (fromKey == null || inFromRange(key, false)) &&
2266 (toKey == null || inToRange(key, true));
2267 }
2268
2269 protected boolean inToRange(K key, boolean forceInclusive) {
2270 int ret = keyAnalyzer.compare(key, toKey);
2271 if(toInclusive || forceInclusive)
2272 return ret <= 0;
2273 else
2274 return ret < 0;
2275 }
2276
2277 protected boolean inFromRange(K key, boolean forceInclusive) {
2278 int ret = keyAnalyzer.compare(key, fromKey);
2279 if (fromInclusive || forceInclusive)
2280 return ret >= 0;
2281 else
2282 return ret > 0;
2283 }
2284 }
2285 }