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