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