001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * https://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.commons.collections4.trie; 018 019import java.io.IOException; 020import java.io.ObjectInputStream; 021import java.io.ObjectOutputStream; 022import java.util.AbstractCollection; 023import java.util.AbstractMap; 024import java.util.AbstractSet; 025import java.util.Collection; 026import java.util.Collections; 027import java.util.Comparator; 028import java.util.ConcurrentModificationException; 029import java.util.Iterator; 030import java.util.Map; 031import java.util.NoSuchElementException; 032import java.util.Objects; 033import java.util.Set; 034import java.util.SortedMap; 035 036import org.apache.commons.collections4.OrderedMapIterator; 037import org.apache.commons.collections4.Trie; 038 039/** 040 * This class implements the base PATRICIA algorithm and everything that 041 * is related to the {@link Map} interface. 042 * 043 * @param <K> The type of the keys in this map 044 * @param <V> The type of the values in this map 045 * @since 4.0 046 */ 047public abstract class AbstractPatriciaTrie<K, V> extends AbstractBitwiseTrie<K, V> { 048 049 /** 050 * A range view of the {@link Trie}. 051 */ 052 private abstract class AbstractRangeMap extends AbstractMap<K, V> 053 implements SortedMap<K, V> { 054 055 /** The {@link #entrySet()} view. */ 056 private transient volatile Set<Map.Entry<K, V>> entrySet; 057 058 @Override 059 public Comparator<? super K> comparator() { 060 return AbstractPatriciaTrie.this.comparator(); 061 } 062 063 @Override 064 public boolean containsKey(final Object key) { 065 if (!inRange(castKey(key))) { 066 return false; 067 } 068 069 return AbstractPatriciaTrie.this.containsKey(key); 070 } 071 072 /** 073 * Creates and returns an {@link #entrySet()} view of the {@link AbstractRangeMap}. 074 */ 075 protected abstract Set<Map.Entry<K, V>> createEntrySet(); 076 077 /** 078 * Creates and returns a sub-range view of the current {@link AbstractRangeMap}. 079 */ 080 protected abstract SortedMap<K, V> createRangeMap(K fromKey, boolean fromInclusive, 081 K toKey, boolean toInclusive); 082 083 @Override 084 public Set<Map.Entry<K, V>> entrySet() { 085 if (entrySet == null) { 086 entrySet = createEntrySet(); 087 } 088 return entrySet; 089 } 090 091 @Override 092 public V get(final Object key) { 093 if (!inRange(castKey(key))) { 094 return null; 095 } 096 097 return AbstractPatriciaTrie.this.get(key); 098 } 099 100 /** 101 * Gets the FROM Key. 102 */ 103 protected abstract K getFromKey(); 104 105 /** 106 * Gets the TO Key. 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 * Returns true if the provided key is in the FROM range of the {@link AbstractRangeMap}. 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 * Returns true if the provided key is greater than TO and less than FROM. 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 * This form allows the high endpoint (as well as all legit keys). 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 * Returns true if the provided key is in the TO range of the {@link AbstractRangeMap}. 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 * Tests whether or not the {@link #getFromKey()} is in the range. 168 * 169 * @return whether or not the {@link #getFromKey()} is in the range. 170 */ 171 protected abstract boolean isFromInclusive(); 172 173 /** 174 * Tests whether or not the {@link #getToKey()} is in the range. 175 * 176 * @return whether or not the {@link #getToKey()} is in the range. 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 * An iterator for the entries. 221 */ 222 abstract class AbstractTrieIterator<E> implements Iterator<E> { 223 224 /** For fast-fail. */ 225 protected int expectedModCount = AbstractPatriciaTrie.this.modCount; 226 227 protected TrieEntry<K, V> next; // the next node to return 228 protected TrieEntry<K, V> current; // the current entry we're on 229 230 /** 231 * Starts iteration from the root. 232 */ 233 protected AbstractTrieIterator() { 234 next = AbstractPatriciaTrie.this.nextEntry(null); 235 } 236 237 /** 238 * Starts iteration at the given entry. 239 */ 240 protected AbstractTrieIterator(final TrieEntry<K, V> firstEntry) { 241 next = firstEntry; 242 } 243 244 /** 245 * @see PatriciaTrie#nextEntry(TrieEntry) 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 * Returns the next {@link TrieEntry}. 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 * This is an entry set view of the {@link Trie} as returned by {@link Map#entrySet()}. 294 */ 295 private final class EntrySet extends AbstractSet<Map.Entry<K, V>> { 296 297 /** 298 * An {@link Iterator} that returns {@link Entry} Objects. 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 * This is a key set view of the {@link Trie} as returned by {@link Map#keySet()}. 348 */ 349 private final class KeySet extends AbstractSet<K> { 350 351 /** 352 * An {@link Iterator} that returns Key Objects. 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 * A prefix {@link RangeEntrySet} view of the {@link Trie}. 391 */ 392 private final class PrefixRangeEntrySet extends RangeEntrySet { 393 394 /** 395 * An {@link Iterator} for iterating over a prefix search. 396 */ 397 private final class EntryIterator extends AbstractTrieIterator<Map.Entry<K, V>> { 398 399 // values to reset the subtree if we remove it. 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; // the subtree to search within 406 407 /** 408 * Starts iteration at the given entry & search only 409 * within the given subtree. 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 // If the current entry we're removing is the subtree 437 // then we need to find a new subtree parent. 438 boolean needsFixing = false; 439 final int bitIdx = subtree.bitIndex; 440 if (current == subtree) { 441 needsFixing = true; 442 } 443 444 super.remove(); 445 446 // If the subtree changed its bitIndex or we 447 // removed the old subtree, get a new one. 448 if (bitIdx != subtree.bitIndex || needsFixing) { 449 subtree = subtree(prefix, offset, lengthInBits); 450 } 451 452 // If the subtree's bitIndex is less than the 453 // length of our prefix, it's the last item 454 // in the prefix tree. 455 if (lengthInBits >= subtree.bitIndex) { 456 lastOne = true; 457 } 458 } 459 } 460 461 /** 462 * An {@link Iterator} that holds a single {@link TrieEntry}. 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 * Creates a {@link PrefixRangeEntrySet}. 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 * A submap used for prefix views over the {@link Trie}. 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 * Creates a {@link PrefixRangeMap}. 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 * This method does two things. It determines the FROM 608 * and TO range of the {@link PrefixRangeMap} and the number 609 * of elements in the range. This method must be called every 610 * time the {@link Trie} has changed. 611 */ 612 private int fixup() { 613 // The trie has changed since we last found our toKey / fromKey 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 * Returns true if the provided Key is in the FROM range of the {@link PrefixRangeMap}. 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 * Returns true if this {@link PrefixRangeMap}'s key is a prefix of the provided key. 670 */ 671 @Override 672 protected boolean inRange(final K key) { 673 return getKeyAnalyzer().isPrefix(prefix, offsetInBits, lengthInBits, key); 674 } 675 676 /** 677 * Same as {@link #inRange(Object)}. 678 */ 679 @Override 680 protected boolean inRange2(final K key) { 681 return inRange(key); 682 } 683 684 /** 685 * Returns true if the provided Key is in the TO range of the {@link PrefixRangeMap}. 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 * A {@link AbstractRangeMap} that deals with {@link Entry}s. 724 */ 725 private final class RangeEntryMap extends AbstractRangeMap { 726 727 /** The key to start from, null if the beginning. */ 728 private final K fromKey; 729 730 /** The key to end at, null if till the end. */ 731 private final K toKey; 732 733 /** Whether or not the 'from' is inclusive. */ 734 private final boolean fromInclusive; 735 736 /** Whether or not the 'to' is inclusive. */ 737 private final boolean toInclusive; 738 739 /** 740 * Creates a {@link RangeEntryMap}. 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 * Creates a {@link RangeEntryMap} with the fromKey included and 761 * the toKey excluded from the range. 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 * A {@link Set} view of a {@link AbstractRangeMap}. 837 */ 838 private class RangeEntrySet extends AbstractSet<Map.Entry<K, V>> { 839 840 /** 841 * An {@link Iterator} for {@link RangeEntrySet}s. 842 */ 843 private final class EntryIterator extends AbstractTrieIterator<Map.Entry<K, V>> { 844 845 private final K excludedKey; 846 847 /** 848 * Creates a {@link EntryIterator}. 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 * Creates a {@link RangeEntrySet}. 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 * A {@link Reference} allows us to return something through a Method's 962 * argument list. An alternative would be to an Array with a length of 963 * one (1) but that leads to compiler warnings. Computationally and memory 964 * wise there's no difference (except for the need to load the 965 * {@link Reference} Class but that happens only once). 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 * A {@link Trie} is a set of {@link TrieEntry} nodes. 982 * 983 * @param <K> The key type. 984 * @param <V> The value type. 985 */ 986 protected static class TrieEntry<K, V> extends BasicEntry<K, V> { 987 988 private static final long serialVersionUID = 4596023148184140013L; 989 990 /** The index this entry is comparing. */ 991 protected int bitIndex; 992 993 /** The parent of this entry. */ 994 protected TrieEntry<K, V> parent; 995 996 /** The left child of this entry. */ 997 protected TrieEntry<K, V> left; 998 999 /** The right child of this entry. */ 1000 protected TrieEntry<K, V> right; 1001 1002 /** The entry who uplinks to this entry. */ 1003 protected TrieEntry<K, V> predecessor; 1004 1005 /** 1006 * Constructs a new instance. 1007 * 1008 * @param key The entry's key. 1009 * @param value The entry's value. 1010 * @param bitIndex The entry's bitIndex. 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 * Tests whether the entry is storing a key. Only the root can potentially be empty, all other nodes must have a key. 1023 * 1024 * @return Whether the entry is storing a key 1025 */ 1026 public boolean isEmpty() { 1027 return key == null; 1028 } 1029 1030 /** 1031 * Tests whether the left or right child is a loopback. 1032 * 1033 * @return Whether the left or right child is a loopback. 1034 */ 1035 public boolean isExternalNode() { 1036 return !isInternalNode(); 1037 } 1038 1039 /** 1040 * Tests that neither the left nor right child is a loopback. 1041 * 1042 * @return That neither the left nor right child is a loopback. 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 //buffer.append("bitIndex=").append(bitIndex).append(", "); 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 * An {@link OrderedMapIterator} for a {@link Trie}. 1111 */ 1112 private final class TrieMapIterator extends AbstractTrieIterator<K> implements OrderedMapIterator<K, V> { 1113 1114 protected TrieEntry<K, V> previous; // the previous node to return 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 * This is a value view of the {@link Trie} as returned by {@link Map#values()}. 1182 */ 1183 private final class Values extends AbstractCollection<V> { 1184 1185 /** 1186 * An {@link Iterator} that returns Value Objects. 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 * Returns true if 'next' is a valid uplink coming from 'from'. 1232 */ 1233 static boolean isValidUplink(final TrieEntry<?, ?> next, final TrieEntry<?, ?> from) { 1234 return next != null && next.bitIndex <= from.bitIndex && !next.isEmpty(); 1235 } 1236 1237 /** The root node of the {@link Trie}. */ 1238 private transient TrieEntry<K, V> root = new TrieEntry<>(null, null, -1); 1239 1240 /** 1241 * Each of these fields are initialized to contain an instance of the 1242 * appropriate view the first time this view is requested. The views are 1243 * stateless, so there's no reason to create more than one of each. 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 /** The current size of the {@link Trie}. */ 1252 private transient int size; 1253 1254 /** 1255 * The number of times this {@link Trie} has been modified. 1256 * It's used to detect concurrent modifications and fail-fast the {@link Iterator}s. 1257 */ 1258 protected transient int modCount; 1259 1260 /** 1261 * Constructs a new {@link Trie} using the given {@link KeyAnalyzer}. 1262 * 1263 * @param keyAnalyzer The {@link KeyAnalyzer}. 1264 */ 1265 protected AbstractPatriciaTrie(final KeyAnalyzer<? super K> keyAnalyzer) { 1266 super(keyAnalyzer); 1267 } 1268 1269 /** 1270 * Constructs a new {@link Trie} using the given {@link KeyAnalyzer} and initializes the 1271 * {@link Trie} with the values from the provided {@link Map}. 1272 * 1273 * @param keyAnalyzer The {@link KeyAnalyzer}. 1274 * @param map The source map. 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 * Adds the given {@link TrieEntry} to the {@link Trie}. 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 // if we inserted an uplink, set the predecessor on it 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 * Returns a key-value mapping associated with the least key greater 1331 * than or equal to the given key, or null if there is no such key. 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 // search key < found.key 1352 // found is a ceiling candidate, walk backward to find the smallest entry still >= key 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 // search key > found.key 1362 // walk forward to find the first entry.key > key 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 // we should have exited above. 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 * A helper method to decrement the {@link Trie} size and increment the modification counter. 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 * Returns the first entry the {@link Trie} is storing. 1434 * <p> 1435 * This is implemented by going always to the left until we encounter a valid uplink. That uplink is the first key. 1436 * </p> 1437 * 1438 * @return The first entry the {@link Trie} is storing. 1439 * @since 4.6.0 1440 */ 1441 public TrieEntry<K, V> firstEntry() { 1442 // if Trie is empty, no first node. 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 * Returns a key-value mapping associated with the greatest key 1460 * less than or equal to the given key, or null if there is no such key. 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 // we should have exited above. 1509 throw new IllegalStateException("invalid lookup: " + key); 1510 } 1511 1512 /** 1513 * Goes left through the tree until it finds a valid node. 1514 */ 1515 TrieEntry<K, V> followLeft(TrieEntry<K, V> node) { 1516 while (true) { 1517 TrieEntry<K, V> child = node.left; 1518 // if we hit root and it didn't have a node, go right instead. 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 * Traverses down the right path until it finds an uplink. 1533 */ 1534 TrieEntry<K, V> followRight(TrieEntry<K, V> node) { 1535 // if Trie is empty, no last entry. 1536 if (node.right == null) { 1537 return null; 1538 } 1539 1540 // Go as far right as possible, until we encounter an uplink. 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 * Gets the entry associated with the specified key in the 1556 * PatriciaTrieBase. Returns null if the map contains no mapping 1557 * for this key. 1558 * <p> 1559 * This may throw ClassCastException if the object is not of type K. 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 * Gets the nearest entry for a given key. This is useful 1574 * for finding knowing if a given key exists (and finding the value 1575 * for it), or for inserting the key. 1576 * 1577 * The actual get implementation. This is very similar to 1578 * selectR but with the exception that it might return the 1579 * root Entry even if it's empty. 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 * Gets a view of this {@link Trie} of all elements that are prefixed 1600 * by the number of bits in the given Key. 1601 * <p> 1602 * The view that this returns is optimized to have a very efficient 1603 * {@link Iterator}. The {@link SortedMap#firstKey()}, 1604 * {@link SortedMap#lastKey()} & {@link Map#size()} methods must 1605 * iterate over all possible values in order to determine the results. 1606 * This information is cached until the PATRICIA {@link Trie} changes. 1607 * All other methods (except {@link Iterator}) must compare the given 1608 * key to the prefix to ensure that it is within the range of the view. 1609 * The {@link Iterator}'s remove method must also relocate the subtree 1610 * that contains the prefixes if the entry holding the subtree is 1611 * removed or changes. Changing the subtree takes O(K) time. 1612 * 1613 * @param key The key to use in the search 1614 * @param offsetInBits The prefix offset 1615 * @param lengthInBits The number of significant prefix bits 1616 * @return A {@link SortedMap} view of this {@link Trie} with all elements whose 1617 * key is prefixed by the search key 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 * Returns an entry strictly higher than the given key, 1637 * or null if no such entry exists. 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 // If data in root, and more after -- return it. 1645 if (size() > 1) { 1646 return nextEntry(root); 1647 } 1648 // If no more after, no higher entry. 1649 return null; 1650 } 1651 // Root is empty & we want something after empty, return first. 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 // we should have exited above. 1692 throw new IllegalStateException("invalid lookup: " + key); 1693 } 1694 1695 /** 1696 * A helper method to increment the modification counter. 1697 */ 1698 private void incrementModCount() { 1699 ++modCount; 1700 } 1701 1702 /** 1703 * A helper method to increment the {@link Trie} size and the modification counter. 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 * Returns the last entry the {@link Trie} is storing. 1720 * 1721 * <p> 1722 * This is implemented by going always to the right until we encounter a valid uplink. That uplink is the last key. 1723 * </p> 1724 * 1725 * @return The last entry the {@link Trie} is storing. 1726 * @since 4.6.0 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 * Returns a key-value mapping associated with the greatest key 1743 * strictly less than the given key, or null if there is no such key. 1744 */ 1745 TrieEntry<K, V> lowerEntry(final K key) { 1746 final int lengthInBits = lengthInBits(key); 1747 1748 if (lengthInBits == 0) { 1749 return null; // there can never be anything before root. 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 // we should have exited above. 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 * Returns the entry lexicographically after the given entry. 1796 * If the given entry is null, returns the first node. 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 * Scans for the next node, starting at the specified point, and using 'previous' 1807 * as a hint that the last node we returned was 'previous' (so we know not to return 1808 * it again). If 'tree' is non-null, this will limit the search to the given tree. 1809 * 1810 * The basic premise is that each iteration can follow the following steps: 1811 * 1812 * 1) Scan all the way to the left. 1813 * a) If we already started from this node last time, proceed to Step 2. 1814 * b) If a valid uplink is found, use it. 1815 * c) If the result is an empty node (root not set), break the scan. 1816 * d) If we already returned the left node, break the scan. 1817 * 1818 * 2) Check the right. 1819 * a) If we already returned the right node, proceed to Step 3. 1820 * b) If it is a valid uplink, use it. 1821 * c) Do Step 1 from the right node. 1822 * 1823 * 3) Back up through the parents until we encounter find a parent 1824 * that we're not the right child of. 1825 * 1826 * 4) If there's no right child of that parent, the iteration is finished. 1827 * Otherwise continue to Step 5. 1828 * 1829 * 5) Check to see if the right child is a valid uplink. 1830 * a) If we already returned that child, proceed to Step 6. 1831 * Otherwise, use it. 1832 * 1833 * 6) If the right child of the parent is the parent itself, we've 1834 * already found & returned the end of the Trie, so exit. 1835 * 1836 * 7) Do Step 1 on the parent's right child. 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 // Only look at the left if this was a recursive or 1844 // the first check, otherwise we know we've already looked 1845 // at the left. 1846 if (previous == null || start != previous.predecessor) { 1847 while (!current.left.isEmpty()) { 1848 // stop traversing if we've already 1849 // returned the left of this node. 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 // If there's no data at all, exit. 1863 if (current.isEmpty()) { 1864 return null; 1865 } 1866 1867 // If we've already returned the left, 1868 // and the immediate right is null, 1869 // there's only one entry in the Trie 1870 // which is stored at the root. 1871 // 1872 // / ("") <-- root 1873 // \_/ \ 1874 // null <-- 'current' 1875 // 1876 if (current.right == null) { 1877 return null; 1878 } 1879 1880 // If nothing valid on the left, try the right. 1881 if (previous != current.right) { 1882 // See if it immediately is valid. 1883 if (isValidUplink(current.right, current)) { 1884 return current.right; 1885 } 1886 1887 // Must search on the right's side if it wasn't initially valid. 1888 return nextEntryImpl(current.right, previous, tree); 1889 } 1890 1891 // Neither left nor right are valid, find the first parent 1892 // whose child did not come from the right & traverse it. 1893 while (current == current.parent.right) { 1894 // If we're going to traverse to above the subtree, stop. 1895 if (current == tree) { 1896 return null; 1897 } 1898 1899 current = current.parent; 1900 } 1901 1902 // If we're on the top of the subtree, we can't go any higher. 1903 if (current == tree) { 1904 return null; 1905 } 1906 1907 // If there's no right, the parent must be root, so we're done. 1908 if (current.parent.right == null) { 1909 return null; 1910 } 1911 1912 // If the parent's right points to itself, we've found one. 1913 if (previous != current.parent.right 1914 && isValidUplink(current.parent.right, current.parent)) { 1915 return current.parent.right; 1916 } 1917 1918 // If the parent's right is itself, there can't be any more nodes. 1919 if (current.parent.right == current.parent) { 1920 return null; 1921 } 1922 1923 // We need to traverse down the parent's right's path. 1924 return nextEntryImpl(current.parent.right, previous, tree); 1925 } 1926 1927 /** 1928 * Returns the entry lexicographically after the given entry. 1929 * If the given entry is null, returns the first node. 1930 * 1931 * This will traverse only within the subtree. If the given node 1932 * is not within the subtree, this will have undefined results. 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 * Returns the node lexicographically before the given node (or null if none). 1960 * 1961 * This follows four simple branches: 1962 * - If the uplink that returned us was a right uplink: 1963 * - If predecessor's left is a valid uplink from predecessor, return it. 1964 * - Else, follow the right path from the predecessor's left. 1965 * - If the uplink that returned us was a left uplink: 1966 * - Loop back through parents until we encounter a node where 1967 * node != node.parent.left. 1968 * - If node.parent.left is uplink from node.parent: 1969 * - If node.parent.left is not root, return it. 1970 * - If it is root & root isEmpty, return null. 1971 * - If it is root & root !isEmpty, return root. 1972 * - If node.parent.left is not uplink from node.parent: 1973 * - Follow right path for first right child from node.parent.left 1974 * 1975 * @param start The start entry 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) { // can be null if we're looking up root. 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 // The only place to store a key with a length 2028 // of zero bits is the root node 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()) { // <- must be the root 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)) { // in 99.999...9% the case 2051 /* NEW KEY+VALUE TUPLE */ 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 // A bits of the Key are zero. The only place to 2059 // store such a Key is the root Node! 2060 2061 /* NULL BIT KEY */ 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) { // NOPMD 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 * Deserializes an instance from an ObjectInputStream. 2081 * 2082 * @param in The source ObjectInputStream. 2083 * @throws IOException Any of the usual Input/Output related exceptions. 2084 * @throws ClassNotFoundException A class of a serialized object cannot be found. 2085 */ 2086 @SuppressWarnings("unchecked") // This will fail at runtime if the stream is incorrect 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 * {@inheritDoc} 2100 * 2101 * @throws ClassCastException if provided key is of an incompatible type 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 * Removes a single entry from the {@link Trie}. 2133 * 2134 * If we found a Key (Entry h) then figure out if it's 2135 * an internal (hard to remove) or external Entry (easy 2136 * to remove) 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 * Removes an external entry from the {@link Trie}. 2153 * 2154 * If it's an external Entry then just remove it. 2155 * This is very easy and straight forward. 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 // either the parent is changing, or the predecessor is changing. 2175 if (child.bitIndex > parent.bitIndex) { 2176 child.parent = parent; 2177 } else { 2178 child.predecessor = parent; 2179 } 2180 2181 } 2182 2183 /** 2184 * Removes an internal entry from the {@link Trie}. 2185 * 2186 * If it's an internal Entry then "good luck" with understanding 2187 * this code. The Idea is essentially that Entry p takes Entry h's 2188 * place in the trie which requires some re-wiring. 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 // Set P's bitIndex 2201 p.bitIndex = h.bitIndex; 2202 2203 // Fix P's parent, predecessor and child Nodes 2204 { 2205 final TrieEntry<K, V> parent = p.parent; 2206 final TrieEntry<K, V> child = p.left == h ? p.right : p.left; 2207 2208 // if it was looping to itself previously, 2209 // it will now be pointed from its parent 2210 // (if we aren't removing its parent -- 2211 // in that case, it remains looping to itself). 2212 // otherwise, it will continue to have the same 2213 // predecessor. 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 // Fix H's parent and child Nodes 2230 { 2231 // If H is a parent of its left and right child 2232 // then change them to P 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 // Change H's parent 2242 if (h.parent.left == h) { 2243 h.parent.left = p; 2244 } else { 2245 h.parent.right = p; 2246 } 2247 } 2248 2249 // Copy the remaining fields from H to P 2250 //p.bitIndex = h.bitIndex; 2251 p.parent = h.parent; 2252 p.left = h.left; 2253 p.right = h.right; 2254 2255 // Make sure that if h was pointing to any uplinks, 2256 // p now points to them. 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 * Returns the {@link Entry} whose key is closest in a bitwise XOR 2268 * metric to the given key. This is NOT lexicographic closeness. 2269 * For example, given the keys: 2270 * 2271 * <ol> 2272 * <li>D = 1000100</li> 2273 * <li>H = 1001000</li> 2274 * <li>L = 1001100</li> 2275 * </ol> 2276 * 2277 * If the {@link Trie} contained 'H' and 'L', a lookup of 'D' would 2278 * return 'L', because the XOR distance between D & L is smaller 2279 * than the XOR distance between D & H. 2280 * 2281 * @param key The key to use in the search 2282 * @return The {@link Entry} whose key is closest in a bitwise XOR metric 2283 * to the provided key 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 * Returns the key that is closest in a bitwise XOR metric to the 2296 * provided key. This is NOT lexicographic closeness! 2297 * 2298 * For example, given the keys: 2299 * 2300 * <ol> 2301 * <li>D = 1000100</li> 2302 * <li>H = 1001000</li> 2303 * <li>L = 1001100</li> 2304 * </ol> 2305 * 2306 * If the {@link Trie} contained 'H' and 'L', a lookup of 'D' would 2307 * return 'L', because the XOR distance between D & L is smaller 2308 * than the XOR distance between D & H. 2309 * 2310 * @param key The key to use in the search 2311 * @return The key that is closest in a bitwise XOR metric to the provided key 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 // If we hit the root Node and it is empty 2327 // we have to look for an alternative best 2328 // matching node. 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 * Returns the value whose key is closest in a bitwise XOR metric to 2348 * the provided key. This is NOT lexicographic closeness! 2349 * 2350 * For example, given the keys: 2351 * 2352 * <ol> 2353 * <li>D = 1000100</li> 2354 * <li>H = 1001000</li> 2355 * <li>L = 1001100</li> 2356 * </ol> 2357 * 2358 * If the {@link Trie} contained 'H' and 'L', a lookup of 'D' would 2359 * return 'L', because the XOR distance between D & L is smaller 2360 * than the XOR distance between D & H. 2361 * 2362 * @param key The key to use in the search 2363 * @return The value whose key is closest in a bitwise XOR metric 2364 * to the provided key 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 * Finds the subtree that contains the prefix. 2386 * 2387 * This is very similar to getR but with the difference that 2388 * we stop the lookup if h.bitIndex > lengthInBits. 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 // Make sure the entry is valid for a subtree. 2407 final TrieEntry<K, V> entry = current.isEmpty() ? path : current; 2408 2409 // If entry is root, it can't be empty. 2410 if (entry.isEmpty()) { 2411 return null; 2412 } 2413 2414 final int endIndexInBits = offsetInBits + lengthInBits; 2415 2416 // if root && length of root is less than length of lookup, 2417 // there's nothing. 2418 // (this prevents returning the whole subtree if root has an empty 2419 // string and we want to lookup things with "\0") 2420 if (entry == root && lengthInBits(entry.getKey()) < endIndexInBits) { 2421 return null; 2422 } 2423 2424 // Found key's length-th bit differs from our key 2425 // which means it cannot be the prefix... 2426 if (isBitSet(prefix, endIndexInBits - 1, endIndexInBits) 2427 != isBitSet(entry.key, lengthInBits - 1, lengthInBits(entry.key))) { 2428 return null; 2429 } 2430 2431 // ... or there are less than 'length' equal bits 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 * Serializes this object to an ObjectOutputStream. 2457 * 2458 * @param out The target ObjectOutputStream. 2459 * @throws IOException thrown when an I/O errors occur writing to the target stream. 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}