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