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 * http://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.bidimap; 018 019import static org.apache.commons.collections4.bidimap.TreeBidiMap.DataElement.KEY; 020import static org.apache.commons.collections4.bidimap.TreeBidiMap.DataElement.VALUE; 021 022import java.io.IOException; 023import java.io.ObjectInputStream; 024import java.io.ObjectOutputStream; 025import java.io.Serializable; 026import java.util.AbstractSet; 027import java.util.ConcurrentModificationException; 028import java.util.Iterator; 029import java.util.Map; 030import java.util.NoSuchElementException; 031import java.util.Objects; 032import java.util.Set; 033 034import org.apache.commons.collections4.KeyValue; 035import org.apache.commons.collections4.MapIterator; 036import org.apache.commons.collections4.OrderedBidiMap; 037import org.apache.commons.collections4.OrderedIterator; 038import org.apache.commons.collections4.OrderedMapIterator; 039import org.apache.commons.collections4.iterators.EmptyOrderedMapIterator; 040import org.apache.commons.collections4.keyvalue.UnmodifiableMapEntry; 041 042/** 043 * Red-Black tree-based implementation of BidiMap where all objects added 044 * implement the {@code Comparable} interface. 045 * <p> 046 * This class guarantees that the map will be in both ascending key order 047 * and ascending value order, sorted according to the natural order for 048 * the key's and value's classes. 049 * </p> 050 * <p> 051 * This Map is intended for applications that need to be able to look 052 * up a key-value pairing by either key or value, and need to do so 053 * with equal efficiency. 054 * </p> 055 * <p> 056 * While that goal could be accomplished by taking a pair of TreeMaps 057 * and redirecting requests to the appropriate TreeMap (e.g., 058 * containsKey would be directed to the TreeMap that maps values to 059 * keys, containsValue would be directed to the TreeMap that maps keys 060 * to values), there are problems with that implementation. 061 * If the data contained in the TreeMaps is large, the cost of redundant 062 * storage becomes significant. The {@link DualTreeBidiMap} and 063 * {@link DualHashBidiMap} implementations use this approach. 064 * </p> 065 * <p> 066 * This solution keeps minimizes the data storage by holding data only once. 067 * The red-black algorithm is based on {@link java.util.TreeMap}, but has been modified 068 * to simultaneously map a tree node by key and by value. This doubles the 069 * cost of put operations (but so does using two TreeMaps), and nearly doubles 070 * the cost of remove operations (there is a savings in that the lookup of the 071 * node to be removed only has to be performed once). And since only one node 072 * contains the key and value, storage is significantly less than that 073 * required by two TreeMaps. 074 * </p> 075 * <p> 076 * The Map.Entry instances returned by the appropriate methods will 077 * not allow setValue() and will throw an 078 * UnsupportedOperationException on attempts to call that method. 079 * </p> 080 * 081 * @param <K> the type of the keys in this map 082 * @param <V> the type of the values in this map 083 * @since 3.0 (previously DoubleOrderedMap v2.0) 084 */ 085public class TreeBidiMap<K extends Comparable<K>, V extends Comparable<V>> 086 implements OrderedBidiMap<K, V>, Serializable { 087 088 /** 089 * A view of this map. 090 */ 091 abstract class AbstractView<E> extends AbstractSet<E> { 092 093 /** Whether to return KEY or VALUE order. */ 094 final DataElement orderType; 095 096 /** 097 * Constructs a new instance. 098 * @param orderType the KEY or VALUE int for the order 099 */ 100 AbstractView(final DataElement orderType) { 101 this.orderType = orderType; 102 } 103 104 @Override 105 public void clear() { 106 TreeBidiMap.this.clear(); 107 } 108 109 @Override 110 public int size() { 111 return TreeBidiMap.this.size(); 112 } 113 } 114 115 /** 116 * An iterator over the map. 117 */ 118 abstract class AbstractViewIterator { 119 120 /** Whether to return KEY or VALUE order. */ 121 private final DataElement orderType; 122 /** The last node returned by the iterator. */ 123 Node<K, V> lastReturnedNode; 124 /** The next node to be returned by the iterator. */ 125 private Node<K, V> nextNode; 126 /** The previous node in the sequence returned by the iterator. */ 127 private Node<K, V> previousNode; 128 /** The modification count. */ 129 private int expectedModifications; 130 131 /** 132 * Constructs a new instance. 133 * @param orderType the KEY or VALUE int for the order 134 */ 135 AbstractViewIterator(final DataElement orderType) { 136 this.orderType = orderType; 137 expectedModifications = modifications; 138 nextNode = leastNode(rootNode[orderType.ordinal()], orderType); 139 lastReturnedNode = null; 140 previousNode = null; 141 } 142 143 public final boolean hasNext() { 144 return nextNode != null; 145 } 146 147 public boolean hasPrevious() { 148 return previousNode != null; 149 } 150 151 protected Node<K, V> navigateNext() { 152 if (nextNode == null) { 153 throw new NoSuchElementException(); 154 } 155 if (modifications != expectedModifications) { 156 throw new ConcurrentModificationException(); 157 } 158 lastReturnedNode = nextNode; 159 previousNode = nextNode; 160 nextNode = nextGreater(nextNode, orderType); 161 return lastReturnedNode; 162 } 163 164 protected Node<K, V> navigatePrevious() { 165 if (previousNode == null) { 166 throw new NoSuchElementException(); 167 } 168 if (modifications != expectedModifications) { 169 throw new ConcurrentModificationException(); 170 } 171 nextNode = lastReturnedNode; 172 if (nextNode == null) { 173 nextNode = nextGreater(previousNode, orderType); 174 } 175 lastReturnedNode = previousNode; 176 previousNode = nextSmaller(previousNode, orderType); 177 return lastReturnedNode; 178 } 179 180 public final void remove() { 181 if (lastReturnedNode == null) { 182 throw new IllegalStateException(); 183 } 184 if (modifications != expectedModifications) { 185 throw new ConcurrentModificationException(); 186 } 187 doRedBlackDelete(lastReturnedNode); 188 expectedModifications++; 189 lastReturnedNode = null; 190 if (nextNode == null) { 191 previousNode = greatestNode(rootNode[orderType.ordinal()], orderType); 192 } else { 193 previousNode = nextSmaller(nextNode, orderType); 194 } 195 } 196 } 197 198 enum DataElement { 199 KEY("key"), VALUE("value"); 200 201 private final String description; 202 203 /** 204 * Creates a new TreeBidiMap.DataElement. 205 * 206 * @param description the description for the element 207 */ 208 DataElement(final String description) { 209 this.description = description; 210 } 211 212 @Override 213 public String toString() { 214 return description; 215 } 216 } 217 /** 218 * A view of this map. 219 */ 220 final class EntryView extends AbstractView<Map.Entry<K, V>> { 221 222 EntryView() { 223 super(KEY); 224 } 225 226 @Override 227 public boolean contains(final Object obj) { 228 if (!(obj instanceof Map.Entry)) { 229 return false; 230 } 231 final Map.Entry<?, ?> entry = (Map.Entry<?, ?>) obj; 232 final Object value = entry.getValue(); 233 final Node<K, V> node = lookupKey(entry.getKey()); 234 return node != null && Objects.equals(node.getValue(), value); 235 } 236 237 @Override 238 public Iterator<Map.Entry<K, V>> iterator() { 239 return new ViewMapEntryIterator(); 240 } 241 242 @Override 243 public boolean remove(final Object obj) { 244 if (!(obj instanceof Map.Entry)) { 245 return false; 246 } 247 final Map.Entry<?, ?> entry = (Map.Entry<?, ?>) obj; 248 final Object value = entry.getValue(); 249 final Node<K, V> node = lookupKey(entry.getKey()); 250 if (node != null && Objects.equals(node.getValue(), value)) { 251 doRedBlackDelete(node); 252 return true; 253 } 254 return false; 255 } 256 } 257 /** 258 * The inverse map implementation. 259 */ 260 final class Inverse implements OrderedBidiMap<V, K> { 261 262 /** Store the keySet once created. */ 263 private Set<V> inverseKeySet; 264 /** Store the valuesSet once created. */ 265 private Set<K> inverseValuesSet; 266 /** Store the entrySet once created. */ 267 private Set<Map.Entry<V, K>> inverseEntrySet; 268 269 @Override 270 public void clear() { 271 TreeBidiMap.this.clear(); 272 } 273 274 @Override 275 public boolean containsKey(final Object key) { 276 return TreeBidiMap.this.containsValue(key); 277 } 278 279 @Override 280 public boolean containsValue(final Object value) { 281 return TreeBidiMap.this.containsKey(value); 282 } 283 284 @Override 285 public Set<Map.Entry<V, K>> entrySet() { 286 if (inverseEntrySet == null) { 287 inverseEntrySet = new InverseEntryView(); 288 } 289 return inverseEntrySet; 290 } 291 292 @Override 293 public boolean equals(final Object obj) { 294 return TreeBidiMap.this.doEquals(obj, VALUE); 295 } 296 297 @Override 298 public V firstKey() { 299 if (TreeBidiMap.this.nodeCount == 0) { 300 throw new NoSuchElementException("Map is empty"); 301 } 302 return leastNode(TreeBidiMap.this.rootNode[VALUE.ordinal()], VALUE).getValue(); 303 } 304 305 @Override 306 public K get(final Object key) { 307 return TreeBidiMap.this.getKey(key); 308 } 309 310 @Override 311 public V getKey(final Object value) { 312 return TreeBidiMap.this.get(value); 313 } 314 315 @Override 316 public int hashCode() { 317 return TreeBidiMap.this.doHashCode(VALUE); 318 } 319 320 @Override 321 public OrderedBidiMap<K, V> inverseBidiMap() { 322 return TreeBidiMap.this; 323 } 324 325 @Override 326 public boolean isEmpty() { 327 return TreeBidiMap.this.isEmpty(); 328 } 329 330 @Override 331 public Set<V> keySet() { 332 if (inverseKeySet == null) { 333 inverseKeySet = new ValueView(VALUE); 334 } 335 return inverseKeySet; 336 } 337 338 @Override 339 public V lastKey() { 340 if (TreeBidiMap.this.nodeCount == 0) { 341 throw new NoSuchElementException("Map is empty"); 342 } 343 return greatestNode(TreeBidiMap.this.rootNode[VALUE.ordinal()], VALUE).getValue(); 344 } 345 346 @Override 347 public OrderedMapIterator<V, K> mapIterator() { 348 if (isEmpty()) { 349 return EmptyOrderedMapIterator.<V, K>emptyOrderedMapIterator(); 350 } 351 return new InverseViewMapIterator(VALUE); 352 } 353 354 @Override 355 public V nextKey(final V key) { 356 checkKey(key); 357 final Node<K, V> node = nextGreater(TreeBidiMap.this.<V>lookup(key, VALUE), VALUE); 358 return node == null ? null : node.getValue(); 359 } 360 361 @Override 362 public V previousKey(final V key) { 363 checkKey(key); 364 final Node<K, V> node = TreeBidiMap.this.nextSmaller(TreeBidiMap.this.<V>lookup(key, VALUE), VALUE); 365 return node == null ? null : node.getValue(); 366 } 367 368 @Override 369 public K put(final V key, final K value) { 370 final K result = get(key); 371 TreeBidiMap.this.doPut(value, key); 372 return result; 373 } 374 375 @Override 376 public void putAll(final Map<? extends V, ? extends K> map) { 377 for (final Map.Entry<? extends V, ? extends K> e : map.entrySet()) { 378 put(e.getKey(), e.getValue()); 379 } 380 } 381 382 @Override 383 public K remove(final Object key) { 384 return TreeBidiMap.this.removeValue(key); 385 } 386 387 @Override 388 public V removeValue(final Object value) { 389 return TreeBidiMap.this.remove(value); 390 } 391 392 @Override 393 public int size() { 394 return TreeBidiMap.this.size(); 395 } 396 397 @Override 398 public String toString() { 399 return TreeBidiMap.this.doToString(VALUE); 400 } 401 402 @Override 403 public Set<K> values() { 404 if (inverseValuesSet == null) { 405 inverseValuesSet = new KeyView(VALUE); 406 } 407 return inverseValuesSet; 408 } 409 } 410 /** 411 * A view of this map. 412 */ 413 final class InverseEntryView extends AbstractView<Map.Entry<V, K>> { 414 415 InverseEntryView() { 416 super(VALUE); 417 } 418 419 @Override 420 public boolean contains(final Object obj) { 421 if (!(obj instanceof Map.Entry)) { 422 return false; 423 } 424 final Map.Entry<?, ?> entry = (Map.Entry<?, ?>) obj; 425 final Object value = entry.getValue(); 426 final Node<K, V> node = lookupValue(entry.getKey()); 427 return node != null && Objects.equals(node.getKey(), value); 428 } 429 430 @Override 431 public Iterator<Map.Entry<V, K>> iterator() { 432 return new InverseViewMapEntryIterator(); 433 } 434 435 @Override 436 public boolean remove(final Object obj) { 437 if (!(obj instanceof Map.Entry)) { 438 return false; 439 } 440 final Map.Entry<?, ?> entry = (Map.Entry<?, ?>) obj; 441 final Object value = entry.getValue(); 442 final Node<K, V> node = lookupValue(entry.getKey()); 443 if (node != null && Objects.equals(node.getKey(), value)) { 444 doRedBlackDelete(node); 445 return true; 446 } 447 return false; 448 } 449 } 450 /** 451 * An iterator over the inverse map entries. 452 */ 453 final class InverseViewMapEntryIterator extends AbstractViewIterator implements OrderedIterator<Map.Entry<V, K>> { 454 455 /** 456 * Constructs a new instance. 457 */ 458 InverseViewMapEntryIterator() { 459 super(VALUE); 460 } 461 462 private Map.Entry<V, K> createEntry(final Node<K, V> node) { 463 return new UnmodifiableMapEntry<>(node.getValue(), node.getKey()); 464 } 465 466 @Override 467 public Map.Entry<V, K> next() { 468 return createEntry(navigateNext()); 469 } 470 471 @Override 472 public Map.Entry<V, K> previous() { 473 return createEntry(navigatePrevious()); 474 } 475 } 476 /** 477 * An iterator over the map. 478 */ 479 final class InverseViewMapIterator extends AbstractViewIterator implements OrderedMapIterator<V, K> { 480 481 /** 482 * Creates a new TreeBidiMap.InverseViewMapIterator. 483 */ 484 InverseViewMapIterator(final DataElement orderType) { 485 super(orderType); 486 } 487 488 @Override 489 public V getKey() { 490 if (lastReturnedNode == null) { 491 throw new IllegalStateException( 492 "Iterator getKey() can only be called after next() and before remove()"); 493 } 494 return lastReturnedNode.getValue(); 495 } 496 497 @Override 498 public K getValue() { 499 if (lastReturnedNode == null) { 500 throw new IllegalStateException( 501 "Iterator getValue() can only be called after next() and before remove()"); 502 } 503 return lastReturnedNode.getKey(); 504 } 505 506 @Override 507 public V next() { 508 return navigateNext().getValue(); 509 } 510 511 @Override 512 public V previous() { 513 return navigatePrevious().getValue(); 514 } 515 516 @Override 517 public K setValue(final K value) { 518 throw new UnsupportedOperationException(); 519 } 520 } 521 final class KeyView extends AbstractView<K> { 522 523 /** 524 * Creates a new TreeBidiMap.KeyView. 525 */ 526 KeyView(final DataElement orderType) { 527 super(orderType); 528 } 529 530 @Override 531 public boolean contains(final Object obj) { 532 checkNonNullComparable(obj, KEY); 533 return lookupKey(obj) != null; 534 } 535 536 @Override 537 public Iterator<K> iterator() { 538 return new ViewMapIterator(orderType); 539 } 540 541 @Override 542 public boolean remove(final Object o) { 543 return doRemoveKey(o) != null; 544 } 545 546 } 547 548 /** 549 * A node used to store the data. 550 */ 551 static class Node<K extends Comparable<K>, V extends Comparable<V>> implements Map.Entry<K, V>, KeyValue<K, V> { 552 553 private final K key; 554 private final V value; 555 private final Node<K, V>[] leftNode; 556 private final Node<K, V>[] rightNode; 557 private final Node<K, V>[] parentNode; 558 private final boolean[] blackColor; 559 private int hashCodeValue; 560 private boolean calculatedHashCode; 561 562 /** 563 * Makes a new cell with given key and value, and with null 564 * links, and black (true) colors. 565 * 566 * @param key the key of this node 567 * @param value the value of this node 568 */ 569 @SuppressWarnings("unchecked") 570 Node(final K key, final V value) { 571 this.key = key; 572 this.value = value; 573 leftNode = new Node[2]; 574 rightNode = new Node[2]; 575 parentNode = new Node[2]; 576 blackColor = new boolean[] { true, true }; 577 calculatedHashCode = false; 578 } 579 580 /** 581 * Makes this node the same color as another. 582 * 583 * @param node the node whose color we're adopting 584 * @param dataElement either the {@link DataElement#KEY key} 585 * or the {@link DataElement#VALUE value}. 586 */ 587 private void copyColor(final Node<K, V> node, final DataElement dataElement) { 588 blackColor[dataElement.ordinal()] = node.blackColor[dataElement.ordinal()]; 589 } 590 591 /** 592 * Compares the specified object with this entry for equality. 593 * Returns true if the given object is also a map entry and 594 * the two entries represent the same mapping. 595 * 596 * @param obj the object to be compared for equality with this entry. 597 * @return true if the specified object is equal to this entry. 598 */ 599 @Override 600 public boolean equals(final Object obj) { 601 if (obj == this) { 602 return true; 603 } 604 if (!(obj instanceof Map.Entry)) { 605 return false; 606 } 607 final Map.Entry<?, ?> e = (Map.Entry<?, ?>) obj; 608 return Objects.equals(getKey(), e.getKey()) && Objects.equals(getValue(), e.getValue()); 609 } 610 611 private Object getData(final DataElement dataElement) { 612 switch (dataElement) { 613 case KEY: 614 return getKey(); 615 case VALUE: 616 return getValue(); 617 default: 618 throw new IllegalArgumentException(); 619 } 620 } 621 622 /** 623 * Gets the key. 624 * 625 * @return the key corresponding to this entry. 626 */ 627 @Override 628 public K getKey() { 629 return key; 630 } 631 632 private Node<K, V> getLeft(final DataElement dataElement) { 633 return leftNode[dataElement.ordinal()]; 634 } 635 636 /** 637 * Gets the parent node. 638 * 639 * @param dataElement either the {@link DataElement#KEY key} 640 * or the {@link DataElement#VALUE value}. 641 * @return the parent node, may be null 642 */ 643 private Node<K, V> getParent(final DataElement dataElement) { 644 return parentNode[dataElement.ordinal()]; 645 } 646 647 private Node<K, V> getRight(final DataElement dataElement) { 648 return rightNode[dataElement.ordinal()]; 649 } 650 651 /** 652 * Gets the value. 653 * 654 * @return the value corresponding to this entry. 655 */ 656 @Override 657 public V getValue() { 658 return value; 659 } 660 661 /** 662 * @return the hash code value for this map entry. 663 */ 664 @Override 665 public int hashCode() { 666 if (!calculatedHashCode) { 667 hashCodeValue = getKey().hashCode() ^ getValue().hashCode(); 668 calculatedHashCode = true; 669 } 670 return hashCodeValue; 671 } 672 673 /** 674 * Is this node black? 675 * 676 * @param dataElement either the {@link DataElement#KEY key} 677 * or the {@link DataElement#VALUE value}. 678 * @return true if black (which is represented as a true boolean) 679 */ 680 private boolean isBlack(final DataElement dataElement) { 681 return blackColor[dataElement.ordinal()]; 682 } 683 684 private boolean isLeftChild(final DataElement dataElement) { 685 return parentNode[dataElement.ordinal()] != null 686 && parentNode[dataElement.ordinal()].leftNode[dataElement.ordinal()] == this; 687 } 688 689 /** 690 * Is this node red? 691 * 692 * @param dataElement either the {@link DataElement#KEY key} 693 * or the {@link DataElement#VALUE value}. 694 * @return true if non-black 695 */ 696 private boolean isRed(final DataElement dataElement) { 697 return !blackColor[dataElement.ordinal()]; 698 } 699 700 private boolean isRightChild(final DataElement dataElement) { 701 return parentNode[dataElement.ordinal()] != null 702 && parentNode[dataElement.ordinal()].rightNode[dataElement.ordinal()] == this; 703 } 704 705 /** 706 * Makes this node black. 707 * 708 * @param dataElement either the {@link DataElement#KEY key} 709 * or the {@link DataElement#VALUE value}. 710 */ 711 private void setBlack(final DataElement dataElement) { 712 blackColor[dataElement.ordinal()] = true; 713 } 714 715 private void setLeft(final Node<K, V> node, final DataElement dataElement) { 716 leftNode[dataElement.ordinal()] = node; 717 } 718 719 /** 720 * Sets this node's parent node. 721 * 722 * @param node the new parent node 723 * @param dataElement either the {@link DataElement#KEY key} 724 * or the {@link DataElement#VALUE value}. 725 */ 726 private void setParent(final Node<K, V> node, final DataElement dataElement) { 727 parentNode[dataElement.ordinal()] = node; 728 } 729 730 /** 731 * Makes this node red. 732 * 733 * @param dataElement either the {@link DataElement#KEY key} 734 * or the {@link DataElement#VALUE value}. 735 */ 736 private void setRed(final DataElement dataElement) { 737 blackColor[dataElement.ordinal()] = false; 738 } 739 740 private void setRight(final Node<K, V> node, final DataElement dataElement) { 741 rightNode[dataElement.ordinal()] = node; 742 } 743 744 /** 745 * Optional operation that is not permitted in this implementation. 746 * 747 * @param ignored this parameter is ignored. 748 * @return does not return 749 * @throws UnsupportedOperationException always 750 */ 751 @Override 752 public V setValue(final V ignored) throws UnsupportedOperationException { 753 throw new UnsupportedOperationException("Map.Entry.setValue is not supported"); 754 } 755 756 /** 757 * Exchanges colors with another node. 758 * 759 * @param node the node to swap with 760 * @param dataElement either the {@link DataElement#KEY key} 761 * or the {@link DataElement#VALUE value}. 762 */ 763 private void swapColors(final Node<K, V> node, final DataElement dataElement) { 764 // Swap colors -- old hacker's trick 765 blackColor[dataElement.ordinal()] ^= node.blackColor[dataElement.ordinal()]; 766 node.blackColor[dataElement.ordinal()] ^= blackColor[dataElement.ordinal()]; 767 blackColor[dataElement.ordinal()] ^= node.blackColor[dataElement.ordinal()]; 768 } 769 } 770 771 final class ValueView extends AbstractView<V> { 772 773 /** 774 * Creates a new TreeBidiMap.ValueView. 775 */ 776 ValueView(final DataElement orderType) { 777 super(orderType); 778 } 779 780 @Override 781 public boolean contains(final Object obj) { 782 checkNonNullComparable(obj, VALUE); 783 return lookupValue(obj) != null; 784 } 785 786 @Override 787 public Iterator<V> iterator() { 788 return new InverseViewMapIterator(orderType); 789 } 790 791 @Override 792 public boolean remove(final Object o) { 793 return doRemoveValue(o) != null; 794 } 795 796 } 797 798 /** 799 * An iterator over the map entries. 800 */ 801 final class ViewMapEntryIterator extends AbstractViewIterator implements OrderedIterator<Map.Entry<K, V>> { 802 803 /** 804 * Constructs a new instance. 805 */ 806 ViewMapEntryIterator() { 807 super(KEY); 808 } 809 810 @Override 811 public Map.Entry<K, V> next() { 812 return navigateNext(); 813 } 814 815 @Override 816 public Map.Entry<K, V> previous() { 817 return navigatePrevious(); 818 } 819 } 820 821 /** 822 * An iterator over the map. 823 */ 824 final class ViewMapIterator extends AbstractViewIterator implements OrderedMapIterator<K, V> { 825 826 /** 827 * Constructs a new instance. 828 */ 829 ViewMapIterator(final DataElement orderType) { 830 super(orderType); 831 } 832 833 @Override 834 public K getKey() { 835 if (lastReturnedNode == null) { 836 throw new IllegalStateException( 837 "Iterator getKey() can only be called after next() and before remove()"); 838 } 839 return lastReturnedNode.getKey(); 840 } 841 842 @Override 843 public V getValue() { 844 if (lastReturnedNode == null) { 845 throw new IllegalStateException( 846 "Iterator getValue() can only be called after next() and before remove()"); 847 } 848 return lastReturnedNode.getValue(); 849 } 850 851 @Override 852 public K next() { 853 return navigateNext().getKey(); 854 } 855 856 @Override 857 public K previous() { 858 return navigatePrevious().getKey(); 859 } 860 861 @Override 862 public V setValue(final V value) { 863 throw new UnsupportedOperationException(); 864 } 865 } 866 867 private static final long serialVersionUID = 721969328361807L; 868 869 /** 870 * Checks a key for validity (non-null and implements Comparable) 871 * 872 * @param key the key to be checked 873 * @throws NullPointerException if key is null 874 * @throws ClassCastException if key is not Comparable 875 */ 876 private static void checkKey(final Object key) { 877 checkNonNullComparable(key, KEY); 878 } 879 880 /** 881 * Checks a key and a value for validity (non-null and implements 882 * Comparable) 883 * 884 * @param key the key to be checked 885 * @param value the value to be checked 886 * @throws NullPointerException if key or value is null 887 * @throws ClassCastException if key or value is not Comparable 888 */ 889 private static void checkKeyAndValue(final Object key, final Object value) { 890 checkKey(key); 891 checkValue(value); 892 } 893 894 /** 895 * Checks if an object is fit to be proper input ... has to be 896 * Comparable and non-null. 897 * 898 * @param obj the object being checked 899 * @param dataElement either the {@link DataElement#KEY key} 900 * or the {@link DataElement#VALUE value}. 901 * 902 * @throws NullPointerException if o is null 903 * @throws ClassCastException if o is not Comparable 904 */ 905 private static void checkNonNullComparable(final Object obj, final DataElement dataElement) { 906 Objects.requireNonNull(obj, Objects.toString(dataElement)); 907 if (!(obj instanceof Comparable)) { 908 throw new ClassCastException(dataElement + " must be Comparable"); 909 } 910 } 911 912 /** 913 * Checks a value for validity (non-null and implements Comparable) 914 * 915 * @param value the value to be checked 916 * @throws NullPointerException if value is null 917 * @throws ClassCastException if value is not Comparable 918 */ 919 private static void checkValue(final Object value) { 920 checkNonNullComparable(value, VALUE); 921 } 922 923 /** 924 * Compares two objects. 925 * 926 * @param o1 the first object 927 * @param o2 the second object 928 * @return negative value if o1 < o2; 0 if o1 == o2; positive 929 * value if o1 > o2 930 */ 931 private static <T extends Comparable<T>> int compare(final T o1, final T o2) { 932 return o1.compareTo(o2); 933 } 934 935 /** 936 * Is the specified black red? If the node does not exist, sure, 937 * it's black, thank you. 938 * 939 * @param node the node (may be null) in question 940 * @param dataElement either the {@link DataElement#KEY key} 941 * or the {@link DataElement#VALUE value}. 942 */ 943 private static boolean isBlack(final Node<?, ?> node, final DataElement dataElement) { 944 return node == null || node.isBlack(dataElement); 945 } 946 947 /** 948 * Is the specified node red? If the node does not exist, no, it's 949 * black, thank you. 950 * 951 * @param node the node (may be null) in question 952 * @param dataElement either the {@link DataElement#KEY key} 953 * or the {@link DataElement#VALUE value}. 954 */ 955 private static boolean isRed(final Node<?, ?> node, final DataElement dataElement) { 956 return node != null && node.isRed(dataElement); 957 } 958 959 /** 960 * Forces a node (if it exists) black. 961 * 962 * @param node the node (may be null) in question 963 * @param dataElement either the {@link DataElement#KEY key} 964 * or the {@link DataElement#VALUE value}. 965 */ 966 private static void makeBlack(final Node<?, ?> node, final DataElement dataElement) { 967 if (node != null) { 968 node.setBlack(dataElement); 969 } 970 } 971 972 /** 973 * Forces a node (if it exists) red. 974 * 975 * @param node the node (may be null) in question 976 * @param dataElement either the {@link DataElement#KEY key} 977 * or the {@link DataElement#VALUE value}. 978 */ 979 private static void makeRed(final Node<?, ?> node, final DataElement dataElement) { 980 if (node != null) { 981 node.setRed(dataElement); 982 } 983 } 984 985 private transient Node<K, V>[] rootNode; 986 987 private transient int nodeCount; 988 989 private transient int modifications; 990 991 private transient Set<K> keySet; 992 993 private transient Set<V> valuesSet; 994 995 private transient Set<Map.Entry<K, V>> entrySet; 996 997 private transient Inverse inverse; 998 999 /** 1000 * Constructs a new empty TreeBidiMap. 1001 */ 1002 @SuppressWarnings("unchecked") 1003 public TreeBidiMap() { 1004 rootNode = new Node[2]; 1005 } 1006 1007 /** 1008 * Constructs a new TreeBidiMap by copying an existing Map. 1009 * 1010 * @param map the map to copy 1011 * @throws ClassCastException if the keys/values in the map are 1012 * not Comparable or are not mutually comparable 1013 * @throws NullPointerException if any key or value in the map is null 1014 */ 1015 public TreeBidiMap(final Map<? extends K, ? extends V> map) { 1016 this(); 1017 putAll(map); 1018 } 1019 1020 /** 1021 * Removes all mappings from this map. 1022 */ 1023 @Override 1024 public void clear() { 1025 modify(); 1026 1027 nodeCount = 0; 1028 rootNode[KEY.ordinal()] = null; 1029 rootNode[VALUE.ordinal()] = null; 1030 } 1031 1032 /** 1033 * Checks whether this map contains a mapping for the specified key. 1034 * <p> 1035 * The key must implement {@code Comparable}. 1036 * 1037 * @param key key whose presence in this map is to be tested 1038 * @return true if this map contains a mapping for the specified key 1039 * @throws ClassCastException if the key is of an inappropriate type 1040 * @throws NullPointerException if the key is null 1041 */ 1042 @Override 1043 public boolean containsKey(final Object key) { 1044 checkKey(key); 1045 return lookupKey(key) != null; 1046 } 1047 1048 /** 1049 * Checks whether this map contains a mapping for the specified value. 1050 * <p> 1051 * The value must implement {@code Comparable}. 1052 * 1053 * @param value value whose presence in this map is to be tested 1054 * @return true if this map contains a mapping for the specified value 1055 * @throws ClassCastException if the value is of an inappropriate type 1056 * @throws NullPointerException if the value is null 1057 */ 1058 @Override 1059 public boolean containsValue(final Object value) { 1060 checkValue(value); 1061 return lookupValue(value) != null; 1062 } 1063 1064 /** 1065 * Copies the color from one node to another, dealing with the fact 1066 * that one or both nodes may, in fact, be null. 1067 * 1068 * @param from the node whose color we're copying; may be null 1069 * @param to the node whose color we're changing; may be null 1070 * @param dataElement either the {@link DataElement#KEY key} 1071 * or the {@link DataElement#VALUE value}. 1072 */ 1073 private void copyColor(final Node<K, V> from, final Node<K, V> to, final DataElement dataElement) { 1074 if (to != null) { 1075 if (from == null) { 1076 // by default, make it black 1077 to.setBlack(dataElement); 1078 } else { 1079 to.copyColor(from, dataElement); 1080 } 1081 } 1082 } 1083 1084 /** 1085 * Compares for equals as per the API. 1086 * 1087 * @param obj the object to compare to 1088 * @param dataElement either the {@link DataElement#KEY key} 1089 * or the {@link DataElement#VALUE value}. 1090 * @return true if equal 1091 */ 1092 private boolean doEquals(final Object obj, final DataElement dataElement) { 1093 if (obj == this) { 1094 return true; 1095 } 1096 if (!(obj instanceof Map)) { 1097 return false; 1098 } 1099 final Map<?, ?> other = (Map<?, ?>) obj; 1100 if (other.size() != size()) { 1101 return false; 1102 } 1103 1104 if (nodeCount > 0) { 1105 try { 1106 for (final MapIterator<?, ?> it = getMapIterator(dataElement); it.hasNext(); ) { 1107 final Object key = it.next(); 1108 final Object value = it.getValue(); 1109 if (!value.equals(other.get(key))) { 1110 return false; 1111 } 1112 } 1113 } catch (final ClassCastException | NullPointerException ex) { 1114 return false; 1115 } 1116 } 1117 return true; 1118 } 1119 1120 /** 1121 * Gets the hash code value for this map as per the API. 1122 * 1123 * @param dataElement either the {@link DataElement#KEY key} 1124 * or the {@link DataElement#VALUE value}. 1125 * @return the hash code value for this map 1126 */ 1127 private int doHashCode(final DataElement dataElement) { 1128 int total = 0; 1129 if (nodeCount > 0) { 1130 for (final MapIterator<?, ?> it = getMapIterator(dataElement); it.hasNext(); ) { 1131 final Object key = it.next(); 1132 final Object value = it.getValue(); 1133 total += key.hashCode() ^ value.hashCode(); 1134 } 1135 } 1136 return total; 1137 } 1138 1139 /** 1140 * Puts logic. 1141 * 1142 * @param key the key, always the main map key 1143 * @param value the value, always the main map value 1144 */ 1145 private void doPut(final K key, final V value) { 1146 checkKeyAndValue(key, value); 1147 1148 // store previous and remove previous mappings 1149 doRemoveKey(key); 1150 doRemoveValue(value); 1151 1152 Node<K, V> node = rootNode[KEY.ordinal()]; 1153 if (node == null) { 1154 // map is empty 1155 final Node<K, V> root = new Node<>(key, value); 1156 rootNode[KEY.ordinal()] = root; 1157 rootNode[VALUE.ordinal()] = root; 1158 grow(); 1159 1160 } else { 1161 // add new mapping 1162 while (true) { 1163 final int cmp = compare(key, node.getKey()); 1164 1165 if (cmp == 0) { 1166 // shouldn't happen 1167 throw new IllegalArgumentException("Cannot store a duplicate key (\"" + key + "\") in this Map"); 1168 } 1169 if (cmp < 0) { 1170 if (node.getLeft(KEY) == null) { 1171 final Node<K, V> newNode = new Node<>(key, value); 1172 1173 insertValue(newNode); 1174 node.setLeft(newNode, KEY); 1175 newNode.setParent(node, KEY); 1176 doRedBlackInsert(newNode, KEY); 1177 grow(); 1178 1179 break; 1180 } 1181 node = node.getLeft(KEY); 1182 } else { // cmp > 0 1183 if (node.getRight(KEY) == null) { 1184 final Node<K, V> newNode = new Node<>(key, value); 1185 1186 insertValue(newNode); 1187 node.setRight(newNode, KEY); 1188 newNode.setParent(node, KEY); 1189 doRedBlackInsert(newNode, KEY); 1190 grow(); 1191 1192 break; 1193 } 1194 node = node.getRight(KEY); 1195 } 1196 } 1197 } 1198 } 1199 1200 /** 1201 * Complicated red-black delete stuff. Based on Sun's TreeMap 1202 * implementation, though it's barely recognizable anymore. 1203 * 1204 * @param deletedNode the node to be deleted 1205 */ 1206 private void doRedBlackDelete(final Node<K, V> deletedNode) { 1207 for (final DataElement dataElement : DataElement.values()) { 1208 // if deleted node has both left and children, swap with 1209 // the next greater node 1210 if (deletedNode.getLeft(dataElement) != null && deletedNode.getRight(dataElement) != null) { 1211 swapPosition(nextGreater(deletedNode, dataElement), deletedNode, dataElement); 1212 } 1213 1214 final Node<K, V> replacement = deletedNode.getLeft(dataElement) != null ? 1215 deletedNode.getLeft(dataElement) : deletedNode.getRight(dataElement); 1216 1217 if (replacement != null) { 1218 replacement.setParent(deletedNode.getParent(dataElement), dataElement); 1219 1220 if (deletedNode.getParent(dataElement) == null) { 1221 rootNode[dataElement.ordinal()] = replacement; 1222 } else if (deletedNode == deletedNode.getParent(dataElement).getLeft(dataElement)) { 1223 deletedNode.getParent(dataElement).setLeft(replacement, dataElement); 1224 } else { 1225 deletedNode.getParent(dataElement).setRight(replacement, dataElement); 1226 } 1227 1228 deletedNode.setLeft(null, dataElement); 1229 deletedNode.setRight(null, dataElement); 1230 deletedNode.setParent(null, dataElement); 1231 1232 if (isBlack(deletedNode, dataElement)) { 1233 doRedBlackDeleteFixup(replacement, dataElement); 1234 } 1235 } else { 1236 1237 // replacement is null 1238 if (deletedNode.getParent(dataElement) == null) { 1239 1240 // empty tree 1241 rootNode[dataElement.ordinal()] = null; 1242 } else { 1243 1244 // deleted node had no children 1245 if (isBlack(deletedNode, dataElement)) { 1246 doRedBlackDeleteFixup(deletedNode, dataElement); 1247 } 1248 1249 if (deletedNode.getParent(dataElement) != null) { 1250 if (deletedNode == deletedNode.getParent(dataElement).getLeft(dataElement)) { 1251 deletedNode.getParent(dataElement).setLeft(null, dataElement); 1252 } else { 1253 deletedNode.getParent(dataElement).setRight(null, dataElement); 1254 } 1255 1256 deletedNode.setParent(null, dataElement); 1257 } 1258 } 1259 } 1260 } 1261 shrink(); 1262 } 1263 1264 /** 1265 * Complicated red-black delete stuff. Based on Sun's TreeMap 1266 * implementation, though it's barely recognizable anymore. This 1267 * rebalances the tree (somewhat, as red-black trees are not 1268 * perfectly balanced -- perfect balancing takes longer) 1269 * 1270 * @param replacementNode the node being replaced 1271 * @param dataElement the KEY or VALUE int 1272 */ 1273 private void doRedBlackDeleteFixup(final Node<K, V> replacementNode, final DataElement dataElement) { 1274 Node<K, V> currentNode = replacementNode; 1275 1276 while (currentNode != rootNode[dataElement.ordinal()] && isBlack(currentNode, dataElement)) { 1277 if (currentNode.isLeftChild(dataElement)) { 1278 Node<K, V> siblingNode = getRightChild(getParent(currentNode, dataElement), dataElement); 1279 1280 if (isRed(siblingNode, dataElement)) { 1281 makeBlack(siblingNode, dataElement); 1282 makeRed(getParent(currentNode, dataElement), dataElement); 1283 rotateLeft(getParent(currentNode, dataElement), dataElement); 1284 1285 siblingNode = getRightChild(getParent(currentNode, dataElement), dataElement); 1286 } 1287 1288 if (isBlack(getLeftChild(siblingNode, dataElement), dataElement) 1289 && isBlack(getRightChild(siblingNode, dataElement), dataElement)) { 1290 makeRed(siblingNode, dataElement); 1291 1292 currentNode = getParent(currentNode, dataElement); 1293 } else { 1294 if (isBlack(getRightChild(siblingNode, dataElement), dataElement)) { 1295 makeBlack(getLeftChild(siblingNode, dataElement), dataElement); 1296 makeRed(siblingNode, dataElement); 1297 rotateRight(siblingNode, dataElement); 1298 1299 siblingNode = getRightChild(getParent(currentNode, dataElement), dataElement); 1300 } 1301 1302 copyColor(getParent(currentNode, dataElement), siblingNode, dataElement); 1303 makeBlack(getParent(currentNode, dataElement), dataElement); 1304 makeBlack(getRightChild(siblingNode, dataElement), dataElement); 1305 rotateLeft(getParent(currentNode, dataElement), dataElement); 1306 1307 currentNode = rootNode[dataElement.ordinal()]; 1308 } 1309 } else { 1310 Node<K, V> siblingNode = getLeftChild(getParent(currentNode, dataElement), dataElement); 1311 1312 if (isRed(siblingNode, dataElement)) { 1313 makeBlack(siblingNode, dataElement); 1314 makeRed(getParent(currentNode, dataElement), dataElement); 1315 rotateRight(getParent(currentNode, dataElement), dataElement); 1316 1317 siblingNode = getLeftChild(getParent(currentNode, dataElement), dataElement); 1318 } 1319 1320 if (isBlack(getRightChild(siblingNode, dataElement), dataElement) 1321 && isBlack(getLeftChild(siblingNode, dataElement), dataElement)) { 1322 makeRed(siblingNode, dataElement); 1323 1324 currentNode = getParent(currentNode, dataElement); 1325 } else { 1326 if (isBlack(getLeftChild(siblingNode, dataElement), dataElement)) { 1327 makeBlack(getRightChild(siblingNode, dataElement), dataElement); 1328 makeRed(siblingNode, dataElement); 1329 rotateLeft(siblingNode, dataElement); 1330 1331 siblingNode = getLeftChild(getParent(currentNode, dataElement), dataElement); 1332 } 1333 1334 copyColor(getParent(currentNode, dataElement), siblingNode, dataElement); 1335 makeBlack(getParent(currentNode, dataElement), dataElement); 1336 makeBlack(getLeftChild(siblingNode, dataElement), dataElement); 1337 rotateRight(getParent(currentNode, dataElement), dataElement); 1338 1339 currentNode = rootNode[dataElement.ordinal()]; 1340 } 1341 } 1342 } 1343 1344 makeBlack(currentNode, dataElement); 1345 } 1346 1347 /** 1348 * Complicated red-black insert stuff. Based on Sun's TreeMap 1349 * implementation, though it's barely recognizable anymore. 1350 * 1351 * @param insertedNode the node to be inserted 1352 * @param dataElement the KEY or VALUE int 1353 */ 1354 private void doRedBlackInsert(final Node<K, V> insertedNode, final DataElement dataElement) { 1355 Node<K, V> currentNode = insertedNode; 1356 makeRed(currentNode, dataElement); 1357 1358 while (currentNode != null 1359 && currentNode != rootNode[dataElement.ordinal()] 1360 && isRed(currentNode.getParent(dataElement), dataElement)) { 1361 if (currentNode.isLeftChild(dataElement)) { 1362 final Node<K, V> y = getRightChild(getGrandParent(currentNode, dataElement), dataElement); 1363 1364 if (isRed(y, dataElement)) { 1365 makeBlack(getParent(currentNode, dataElement), dataElement); 1366 makeBlack(y, dataElement); 1367 makeRed(getGrandParent(currentNode, dataElement), dataElement); 1368 1369 currentNode = getGrandParent(currentNode, dataElement); 1370 } else { 1371 //dead code? 1372 if (currentNode.isRightChild(dataElement)) { 1373 currentNode = getParent(currentNode, dataElement); 1374 1375 rotateLeft(currentNode, dataElement); 1376 } 1377 1378 makeBlack(getParent(currentNode, dataElement), dataElement); 1379 makeRed(getGrandParent(currentNode, dataElement), dataElement); 1380 1381 if (getGrandParent(currentNode, dataElement) != null) { 1382 rotateRight(getGrandParent(currentNode, dataElement), dataElement); 1383 } 1384 } 1385 } else { 1386 1387 // just like clause above, except swap left for right 1388 final Node<K, V> y = getLeftChild(getGrandParent(currentNode, dataElement), dataElement); 1389 1390 if (isRed(y, dataElement)) { 1391 makeBlack(getParent(currentNode, dataElement), dataElement); 1392 makeBlack(y, dataElement); 1393 makeRed(getGrandParent(currentNode, dataElement), dataElement); 1394 1395 currentNode = getGrandParent(currentNode, dataElement); 1396 } else { 1397 //dead code? 1398 if (currentNode.isLeftChild(dataElement)) { 1399 currentNode = getParent(currentNode, dataElement); 1400 1401 rotateRight(currentNode, dataElement); 1402 } 1403 1404 makeBlack(getParent(currentNode, dataElement), dataElement); 1405 makeRed(getGrandParent(currentNode, dataElement), dataElement); 1406 1407 if (getGrandParent(currentNode, dataElement) != null) { 1408 rotateLeft(getGrandParent(currentNode, dataElement), dataElement); 1409 } 1410 } 1411 } 1412 } 1413 1414 makeBlack(rootNode[dataElement.ordinal()], dataElement); 1415 } 1416 1417 private V doRemoveKey(final Object key) { 1418 final Node<K, V> node = lookupKey(key); 1419 if (node == null) { 1420 return null; 1421 } 1422 doRedBlackDelete(node); 1423 return node.getValue(); 1424 } 1425 1426 private K doRemoveValue(final Object value) { 1427 final Node<K, V> node = lookupValue(value); 1428 if (node == null) { 1429 return null; 1430 } 1431 doRedBlackDelete(node); 1432 return node.getKey(); 1433 } 1434 1435 /** 1436 * Gets the string form of this map as per AbstractMap. 1437 * 1438 * @param dataElement either the {@link DataElement#KEY key} 1439 * or the {@link DataElement#VALUE value}. 1440 * @return the string form of this map 1441 */ 1442 private String doToString(final DataElement dataElement) { 1443 if (nodeCount == 0) { 1444 return "{}"; 1445 } 1446 final StringBuilder buf = new StringBuilder(nodeCount * 32); 1447 buf.append('{'); 1448 final MapIterator<?, ?> it = getMapIterator(dataElement); 1449 boolean hasNext = it.hasNext(); 1450 while (hasNext) { 1451 final Object key = it.next(); 1452 final Object value = it.getValue(); 1453 buf.append(key == this ? "(this Map)" : key) 1454 .append('=') 1455 .append(value == this ? "(this Map)" : value); 1456 1457 hasNext = it.hasNext(); 1458 if (hasNext) { 1459 buf.append(", "); 1460 } 1461 } 1462 1463 buf.append('}'); 1464 return buf.toString(); 1465 } 1466 1467 /** 1468 * Returns a set view of the entries contained in this map in key order. 1469 * For simple iteration through the map, the MapIterator is quicker. 1470 * <p> 1471 * The set is backed by the map, so changes to the map are reflected in 1472 * the set, and vice-versa. If the map is modified while an iteration over 1473 * the set is in progress, the results of the iteration are undefined. 1474 * <p> 1475 * The set supports element removal, which removes the corresponding mapping 1476 * from the map. It does not support the add or addAll operations. 1477 * The returned MapEntry objects do not support setValue. 1478 * 1479 * @return a set view of the values contained in this map. 1480 */ 1481 @Override 1482 public Set<Map.Entry<K, V>> entrySet() { 1483 if (entrySet == null) { 1484 entrySet = new EntryView(); 1485 } 1486 return entrySet; 1487 } 1488 1489 /** 1490 * Compares for equals as per the API. 1491 * 1492 * @param obj the object to compare to 1493 * @return true if equal 1494 */ 1495 @Override 1496 public boolean equals(final Object obj) { 1497 return this.doEquals(obj, KEY); 1498 } 1499 1500 /** 1501 * Gets the first (lowest) key currently in this map. 1502 * 1503 * @return the first (lowest) key currently in this sorted map 1504 * @throws NoSuchElementException if this map is empty 1505 */ 1506 @Override 1507 public K firstKey() { 1508 if (nodeCount == 0) { 1509 throw new NoSuchElementException("Map is empty"); 1510 } 1511 return leastNode(rootNode[KEY.ordinal()], KEY).getKey(); 1512 } 1513 1514 /** 1515 * Gets the value to which this map maps the specified key. 1516 * Returns null if the map contains no mapping for this key. 1517 * <p> 1518 * The key must implement {@code Comparable}. 1519 * 1520 * @param key key whose associated value is to be returned 1521 * @return the value to which this map maps the specified key, 1522 * or null if the map contains no mapping for this key 1523 * @throws ClassCastException if the key is of an inappropriate type 1524 * @throws NullPointerException if the key is null 1525 */ 1526 @Override 1527 public V get(final Object key) { 1528 checkKey(key); 1529 final Node<K, V> node = lookupKey(key); 1530 return node == null ? null : node.getValue(); 1531 } 1532 1533 /** 1534 * Gets a node's grandparent. mind you, the node, its parent, or 1535 * its grandparent may not exist. No problem. 1536 * 1537 * @param node the node (may be null) in question 1538 * @param dataElement either the {@link DataElement#KEY key} 1539 * or the {@link DataElement#VALUE value}. 1540 */ 1541 private Node<K, V> getGrandParent(final Node<K, V> node, final DataElement dataElement) { 1542 return getParent(getParent(node, dataElement), dataElement); 1543 } 1544 1545 /** 1546 * Returns the key to which this map maps the specified value. 1547 * Returns null if the map contains no mapping for this value. 1548 * <p> 1549 * The value must implement {@code Comparable}. 1550 * 1551 * @param value value whose associated key is to be returned. 1552 * @return the key to which this map maps the specified value, 1553 * or null if the map contains no mapping for this value. 1554 * @throws ClassCastException if the value is of an inappropriate type 1555 * @throws NullPointerException if the value is null 1556 */ 1557 @Override 1558 public K getKey(final Object value) { 1559 checkValue(value); 1560 final Node<K, V> node = lookupValue(value); 1561 return node == null ? null : node.getKey(); 1562 } 1563 1564 /** 1565 * Gets a node's left child. mind you, the node may not exist. no 1566 * problem. 1567 * 1568 * @param node the node (may be null) in question 1569 * @param dataElement either the {@link DataElement#KEY key} 1570 * or the {@link DataElement#VALUE value}. 1571 */ 1572 private Node<K, V> getLeftChild(final Node<K, V> node, final DataElement dataElement) { 1573 return node == null ? null : node.getLeft(dataElement); 1574 } 1575 1576 private MapIterator<?, ?> getMapIterator(final DataElement dataElement) { 1577 switch (dataElement) { 1578 case KEY: 1579 return new ViewMapIterator(KEY); 1580 case VALUE: 1581 return new InverseViewMapIterator(VALUE); 1582 default: 1583 throw new IllegalArgumentException(); 1584 } 1585 } 1586 1587 /** 1588 * Gets a node's parent. mind you, the node, or its parent, may not 1589 * exist. no problem. 1590 * 1591 * @param node the node (may be null) in question 1592 * @param dataElement either the {@link DataElement#KEY key} 1593 * or the {@link DataElement#VALUE value}. 1594 */ 1595 private Node<K, V> getParent(final Node<K, V> node, final DataElement dataElement) { 1596 return node == null ? null : node.getParent(dataElement); 1597 } 1598 1599 /** 1600 * Gets a node's right child. mind you, the node may not exist. no 1601 * problem. 1602 * 1603 * @param node the node (may be null) in question 1604 * @param dataElement either the {@link DataElement#KEY key} 1605 * or the {@link DataElement#VALUE value}. 1606 */ 1607 private Node<K, V> getRightChild(final Node<K, V> node, final DataElement dataElement) { 1608 return node == null ? null : node.getRight(dataElement); 1609 } 1610 1611 /** 1612 * Finds the greatest node from a given node. 1613 * 1614 * @param node the node from which we will start searching 1615 * @param dataElement either the {@link DataElement#KEY key} 1616 * or the {@link DataElement#VALUE value}. 1617 * @return the greatest node, from the specified node 1618 */ 1619 private Node<K, V> greatestNode(final Node<K, V> node, final DataElement dataElement) { 1620 Node<K, V> rval = node; 1621 if (rval != null) { 1622 while (rval.getRight(dataElement) != null) { 1623 rval = rval.getRight(dataElement); 1624 } 1625 } 1626 return rval; 1627 } 1628 1629 /** 1630 * Bumps up the size and note that the map has changed. 1631 */ 1632 private void grow() { 1633 modify(); 1634 nodeCount++; 1635 } 1636 1637 /** 1638 * Gets the hash code value for this map as per the API. 1639 * 1640 * @return the hash code value for this map 1641 */ 1642 @Override 1643 public int hashCode() { 1644 return this.doHashCode(KEY); 1645 } 1646 1647 /** 1648 * Inserts a node by its value. 1649 * 1650 * @param newNode the node to be inserted 1651 * @throws IllegalArgumentException if the node already exists 1652 * in the value mapping 1653 */ 1654 private void insertValue(final Node<K, V> newNode) throws IllegalArgumentException { 1655 Node<K, V> node = rootNode[VALUE.ordinal()]; 1656 1657 while (true) { 1658 final int cmp = compare(newNode.getValue(), node.getValue()); 1659 1660 if (cmp == 0) { 1661 throw new IllegalArgumentException( 1662 "Cannot store a duplicate value (\"" + newNode.getData(VALUE) + "\") in this Map"); 1663 } 1664 if (cmp < 0) { 1665 if (node.getLeft(VALUE) == null) { 1666 node.setLeft(newNode, VALUE); 1667 newNode.setParent(node, VALUE); 1668 doRedBlackInsert(newNode, VALUE); 1669 1670 break; 1671 } 1672 node = node.getLeft(VALUE); 1673 } else { // cmp > 0 1674 if (node.getRight(VALUE) == null) { 1675 node.setRight(newNode, VALUE); 1676 newNode.setParent(node, VALUE); 1677 doRedBlackInsert(newNode, VALUE); 1678 1679 break; 1680 } 1681 node = node.getRight(VALUE); 1682 } 1683 } 1684 } 1685 1686 /** 1687 * Gets the inverse map for comparison. 1688 * 1689 * @return the inverse map 1690 */ 1691 @Override 1692 public OrderedBidiMap<V, K> inverseBidiMap() { 1693 if (inverse == null) { 1694 inverse = new Inverse(); 1695 } 1696 return inverse; 1697 } 1698 1699 /** 1700 * Checks whether the map is empty or not. 1701 * 1702 * @return true if the map is empty 1703 */ 1704 @Override 1705 public boolean isEmpty() { 1706 return nodeCount == 0; 1707 } 1708 1709 /** 1710 * Returns a set view of the keys contained in this map in key order. 1711 * <p> 1712 * The set is backed by the map, so changes to the map are reflected in 1713 * the set, and vice-versa. If the map is modified while an iteration over 1714 * the set is in progress, the results of the iteration are undefined. 1715 * <p> 1716 * The set supports element removal, which removes the corresponding mapping 1717 * from the map. It does not support the add or addAll operations. 1718 * 1719 * @return a set view of the keys contained in this map. 1720 */ 1721 @Override 1722 public Set<K> keySet() { 1723 if (keySet == null) { 1724 keySet = new KeyView(KEY); 1725 } 1726 return keySet; 1727 } 1728 1729 /** 1730 * Gets the last (highest) key currently in this map. 1731 * 1732 * @return the last (highest) key currently in this sorted map 1733 * @throws NoSuchElementException if this map is empty 1734 */ 1735 @Override 1736 public K lastKey() { 1737 if (nodeCount == 0) { 1738 throw new NoSuchElementException("Map is empty"); 1739 } 1740 return greatestNode(rootNode[KEY.ordinal()], KEY).getKey(); 1741 } 1742 1743 /** 1744 * Finds the least node from a given node. 1745 * 1746 * @param node the node from which we will start searching 1747 * @param dataElement either the {@link DataElement#KEY key} 1748 * or the {@link DataElement#VALUE value}. 1749 * @return the smallest node, from the specified node, in the 1750 * specified mapping 1751 */ 1752 private Node<K, V> leastNode(final Node<K, V> node, final DataElement dataElement) { 1753 Node<K, V> rval = node; 1754 if (rval != null) { 1755 while (rval.getLeft(dataElement) != null) { 1756 rval = rval.getLeft(dataElement); 1757 } 1758 } 1759 return rval; 1760 } 1761 1762 /** 1763 * Does the actual lookup of a piece of data. 1764 * 1765 * @param data the key or value to be looked up 1766 * @param dataElement either the {@link DataElement#KEY key} 1767 * or the {@link DataElement#VALUE value}. 1768 * @return the desired Node, or null if there is no mapping of the 1769 * specified data 1770 */ 1771 @SuppressWarnings("unchecked") 1772 private <T extends Comparable<T>> Node<K, V> lookup(final Object data, final DataElement dataElement) { 1773 Node<K, V> rval = null; 1774 Node<K, V> node = rootNode[dataElement.ordinal()]; 1775 1776 while (node != null) { 1777 final int cmp = compare((T) data, (T) node.getData(dataElement)); 1778 if (cmp == 0) { 1779 rval = node; 1780 break; 1781 } 1782 node = cmp < 0 ? node.getLeft(dataElement) : node.getRight(dataElement); 1783 } 1784 1785 return rval; 1786 } 1787 1788 private Node<K, V> lookupKey(final Object key) { 1789 return this.<K>lookup(key, KEY); 1790 } 1791 1792 private Node<K, V> lookupValue(final Object value) { 1793 return this.<V>lookup(value, VALUE); 1794 } 1795 1796 @Override 1797 public OrderedMapIterator<K, V> mapIterator() { 1798 if (isEmpty()) { 1799 return EmptyOrderedMapIterator.<K, V>emptyOrderedMapIterator(); 1800 } 1801 return new ViewMapIterator(KEY); 1802 } 1803 1804 /** 1805 * Increments the modification count -- used to check for 1806 * concurrent modification of the map through the map and through 1807 * an Iterator from one of its Set or Collection views. 1808 */ 1809 private void modify() { 1810 modifications++; 1811 } 1812 1813 /** 1814 * Gets the next larger node from the specified node. 1815 * 1816 * @param node the node to be searched from 1817 * @param dataElement either the {@link DataElement#KEY key} 1818 * or the {@link DataElement#VALUE value}. 1819 * @return the specified node 1820 */ 1821 private Node<K, V> nextGreater(final Node<K, V> node, final DataElement dataElement) { 1822 final Node<K, V> rval; 1823 if (node == null) { 1824 rval = null; 1825 } else if (node.getRight(dataElement) != null) { 1826 // everything to the node's right is larger. The least of 1827 // the right node's descendants is the next larger node 1828 rval = leastNode(node.getRight(dataElement), dataElement); 1829 } else { 1830 // traverse up our ancestry until we find an ancestor that 1831 // is null or one whose left child is our ancestor. If we 1832 // find a null, then this node IS the largest node in the 1833 // tree, and there is no greater node. Otherwise, we are 1834 // the largest node in the subtree on that ancestor's left 1835 // ... and that ancestor is the next greatest node 1836 Node<K, V> parent = node.getParent(dataElement); 1837 Node<K, V> child = node; 1838 1839 while (parent != null && child == parent.getRight(dataElement)) { 1840 child = parent; 1841 parent = parent.getParent(dataElement); 1842 } 1843 rval = parent; 1844 } 1845 return rval; 1846 } 1847 1848 /** 1849 * Gets the next key after the one specified. 1850 * <p> 1851 * The key must implement {@code Comparable}. 1852 * 1853 * @param key the key to search for next from 1854 * @return the next key, null if no match or at end 1855 */ 1856 @Override 1857 public K nextKey(final K key) { 1858 checkKey(key); 1859 final Node<K, V> node = nextGreater(lookupKey(key), KEY); 1860 return node == null ? null : node.getKey(); 1861 } 1862 1863 /** 1864 * Gets the next smaller node from the specified node. 1865 * 1866 * @param node the node to be searched from 1867 * @param dataElement either the {@link DataElement#KEY key} 1868 * or the {@link DataElement#VALUE value}. 1869 * @return the specified node 1870 */ 1871 private Node<K, V> nextSmaller(final Node<K, V> node, final DataElement dataElement) { 1872 final Node<K, V> rval; 1873 if (node == null) { 1874 rval = null; 1875 } else if (node.getLeft(dataElement) != null) { 1876 // everything to the node's left is smaller. The greatest of 1877 // the left node's descendants is the next smaller node 1878 rval = greatestNode(node.getLeft(dataElement), dataElement); 1879 } else { 1880 // traverse up our ancestry until we find an ancestor that 1881 // is null or one whose right child is our ancestor. If we 1882 // find a null, then this node IS the largest node in the 1883 // tree, and there is no greater node. Otherwise, we are 1884 // the largest node in the subtree on that ancestor's right 1885 // ... and that ancestor is the next greatest node 1886 Node<K, V> parent = node.getParent(dataElement); 1887 Node<K, V> child = node; 1888 1889 while (parent != null && child == parent.getLeft(dataElement)) { 1890 child = parent; 1891 parent = parent.getParent(dataElement); 1892 } 1893 rval = parent; 1894 } 1895 return rval; 1896 } 1897 1898 /** 1899 * Gets the previous key before the one specified. 1900 * <p> 1901 * The key must implement {@code Comparable}. 1902 * 1903 * @param key the key to search for previous from 1904 * @return the previous key, null if no match or at start 1905 */ 1906 @Override 1907 public K previousKey(final K key) { 1908 checkKey(key); 1909 final Node<K, V> node = nextSmaller(lookupKey(key), KEY); 1910 return node == null ? null : node.getKey(); 1911 } 1912 1913 /** 1914 * Puts the key-value pair into the map, replacing any previous pair. 1915 * <p> 1916 * When adding a key-value pair, the value may already exist in the map 1917 * against a different key. That mapping is removed, to ensure that the 1918 * value only occurs once in the inverse map. 1919 * <pre> 1920 * BidiMap map1 = new TreeBidiMap(); 1921 * map.put("A","B"); // contains A mapped to B, as per Map 1922 * map.put("A","C"); // contains A mapped to C, as per Map 1923 * 1924 * BidiMap map2 = new TreeBidiMap(); 1925 * map.put("A","B"); // contains A mapped to B, as per Map 1926 * map.put("C","B"); // contains C mapped to B, key A is removed 1927 * </pre> 1928 * <p> 1929 * Both key and value must implement {@code Comparable}. 1930 * 1931 * @param key key with which the specified value is to be associated 1932 * @param value value to be associated with the specified key 1933 * @return the previous value for the key 1934 * @throws ClassCastException if the key is of an inappropriate type 1935 * @throws NullPointerException if the key is null 1936 */ 1937 @Override 1938 public V put(final K key, final V value) { 1939 final V result = get(key); 1940 doPut(key, value); 1941 return result; 1942 } 1943 1944 /** 1945 * Puts all the mappings from the specified map into this map. 1946 * <p> 1947 * All keys and values must implement {@code Comparable}. 1948 * 1949 * @param map the map to copy from 1950 */ 1951 @Override 1952 public void putAll(final Map<? extends K, ? extends V> map) { 1953 for (final Map.Entry<? extends K, ? extends V> e : map.entrySet()) { 1954 put(e.getKey(), e.getValue()); 1955 } 1956 } 1957 1958 /** 1959 * Deserializes the content of the stream. 1960 * 1961 * @param stream the input stream 1962 * @throws IOException if an error occurs while reading from the stream 1963 * @throws ClassNotFoundException if an object read from the stream cannot be loaded 1964 */ 1965 @SuppressWarnings("unchecked") // This will fail at runtime if the stream is incorrect 1966 private void readObject(final ObjectInputStream stream) throws IOException, ClassNotFoundException { 1967 stream.defaultReadObject(); 1968 rootNode = new Node[2]; 1969 final int size = stream.readInt(); 1970 for (int i = 0; i < size; i++) { 1971 final K k = (K) stream.readObject(); 1972 final V v = (V) stream.readObject(); 1973 put(k, v); 1974 } 1975 } 1976 1977 /** 1978 * Removes the mapping for this key from this map if present. 1979 * <p> 1980 * The key must implement {@code Comparable}. 1981 * 1982 * @param key key whose mapping is to be removed from the map. 1983 * @return previous value associated with specified key, 1984 * or null if there was no mapping for key. 1985 * @throws ClassCastException if the key is of an inappropriate type 1986 * @throws NullPointerException if the key is null 1987 */ 1988 @Override 1989 public V remove(final Object key) { 1990 return doRemoveKey(key); 1991 } 1992 1993 /** 1994 * Removes the mapping for this value from this map if present. 1995 * <p> 1996 * The value must implement {@code Comparable}. 1997 * 1998 * @param value value whose mapping is to be removed from the map 1999 * @return previous key associated with specified value, 2000 * or null if there was no mapping for value. 2001 * @throws ClassCastException if the value is of an inappropriate type 2002 * @throws NullPointerException if the value is null 2003 */ 2004 @Override 2005 public K removeValue(final Object value) { 2006 return doRemoveValue(value); 2007 } 2008 2009 /** 2010 * Does a rotate left. standard fare in the world of balanced trees. 2011 * 2012 * @param node the node to be rotated 2013 * @param dataElement either the {@link DataElement#KEY key} 2014 * or the {@link DataElement#VALUE value}. 2015 */ 2016 private void rotateLeft(final Node<K, V> node, final DataElement dataElement) { 2017 final Node<K, V> rightChild = node.getRight(dataElement); 2018 node.setRight(rightChild.getLeft(dataElement), dataElement); 2019 2020 if (rightChild.getLeft(dataElement) != null) { 2021 rightChild.getLeft(dataElement).setParent(node, dataElement); 2022 } 2023 rightChild.setParent(node.getParent(dataElement), dataElement); 2024 2025 if (node.getParent(dataElement) == null) { 2026 // node was the root ... now its right child is the root 2027 rootNode[dataElement.ordinal()] = rightChild; 2028 } else if (node.getParent(dataElement).getLeft(dataElement) == node) { 2029 node.getParent(dataElement).setLeft(rightChild, dataElement); 2030 } else { 2031 node.getParent(dataElement).setRight(rightChild, dataElement); 2032 } 2033 2034 rightChild.setLeft(node, dataElement); 2035 node.setParent(rightChild, dataElement); 2036 } 2037 2038 /** 2039 * Does a rotate right. standard fare in the world of balanced trees. 2040 * 2041 * @param node the node to be rotated 2042 * @param dataElement either the {@link DataElement#KEY key} 2043 * or the {@link DataElement#VALUE value}. 2044 */ 2045 private void rotateRight(final Node<K, V> node, final DataElement dataElement) { 2046 final Node<K, V> leftChild = node.getLeft(dataElement); 2047 node.setLeft(leftChild.getRight(dataElement), dataElement); 2048 if (leftChild.getRight(dataElement) != null) { 2049 leftChild.getRight(dataElement).setParent(node, dataElement); 2050 } 2051 leftChild.setParent(node.getParent(dataElement), dataElement); 2052 2053 if (node.getParent(dataElement) == null) { 2054 // node was the root ... now its left child is the root 2055 rootNode[dataElement.ordinal()] = leftChild; 2056 } else if (node.getParent(dataElement).getRight(dataElement) == node) { 2057 node.getParent(dataElement).setRight(leftChild, dataElement); 2058 } else { 2059 node.getParent(dataElement).setLeft(leftChild, dataElement); 2060 } 2061 2062 leftChild.setRight(node, dataElement); 2063 node.setParent(leftChild, dataElement); 2064 } 2065 2066 /** 2067 * Decrements the size and note that the map has changed. 2068 */ 2069 private void shrink() { 2070 modify(); 2071 nodeCount--; 2072 } 2073 2074 /** 2075 * Returns the number of key-value mappings in this map. 2076 * 2077 * @return the number of key-value mappings in this map 2078 */ 2079 @Override 2080 public int size() { 2081 return nodeCount; 2082 } 2083 2084 /** 2085 * Swaps two nodes (except for their content), taking care of 2086 * special cases where one is the other's parent ... hey, it 2087 * happens. 2088 * 2089 * @param x one node 2090 * @param y another node 2091 * @param dataElement the KEY or VALUE int 2092 */ 2093 private void swapPosition(final Node<K, V> x, final Node<K, V> y, final DataElement dataElement) { 2094 // Save initial values. 2095 final Node<K, V> xFormerParent = x.getParent(dataElement); 2096 final Node<K, V> xFormerLeftChild = x.getLeft(dataElement); 2097 final Node<K, V> xFormerRightChild = x.getRight(dataElement); 2098 final Node<K, V> yFormerParent = y.getParent(dataElement); 2099 final Node<K, V> yFormerLeftChild = y.getLeft(dataElement); 2100 final Node<K, V> yFormerRightChild = y.getRight(dataElement); 2101 final boolean xWasLeftChild = 2102 x.getParent(dataElement) != null && x == x.getParent(dataElement).getLeft(dataElement); 2103 final boolean yWasLeftChild = 2104 y.getParent(dataElement) != null && y == y.getParent(dataElement).getLeft(dataElement); 2105 2106 // Swap, handling special cases of one being the other's parent. 2107 if (x == yFormerParent) { // x was y's parent 2108 x.setParent(y, dataElement); 2109 2110 if (yWasLeftChild) { 2111 y.setLeft(x, dataElement); 2112 y.setRight(xFormerRightChild, dataElement); 2113 } else { 2114 y.setRight(x, dataElement); 2115 y.setLeft(xFormerLeftChild, dataElement); 2116 } 2117 } else { 2118 x.setParent(yFormerParent, dataElement); 2119 2120 if (yFormerParent != null) { 2121 if (yWasLeftChild) { 2122 yFormerParent.setLeft(x, dataElement); 2123 } else { 2124 yFormerParent.setRight(x, dataElement); 2125 } 2126 } 2127 2128 y.setLeft(xFormerLeftChild, dataElement); 2129 y.setRight(xFormerRightChild, dataElement); 2130 } 2131 2132 if (y == xFormerParent) { // y was x's parent 2133 y.setParent(x, dataElement); 2134 2135 if (xWasLeftChild) { 2136 x.setLeft(y, dataElement); 2137 x.setRight(yFormerRightChild, dataElement); 2138 } else { 2139 x.setRight(y, dataElement); 2140 x.setLeft(yFormerLeftChild, dataElement); 2141 } 2142 } else { 2143 y.setParent(xFormerParent, dataElement); 2144 2145 if (xFormerParent != null) { 2146 if (xWasLeftChild) { 2147 xFormerParent.setLeft(y, dataElement); 2148 } else { 2149 xFormerParent.setRight(y, dataElement); 2150 } 2151 } 2152 2153 x.setLeft(yFormerLeftChild, dataElement); 2154 x.setRight(yFormerRightChild, dataElement); 2155 } 2156 2157 // Fix children's parent pointers 2158 if (x.getLeft(dataElement) != null) { 2159 x.getLeft(dataElement).setParent(x, dataElement); 2160 } 2161 2162 if (x.getRight(dataElement) != null) { 2163 x.getRight(dataElement).setParent(x, dataElement); 2164 } 2165 2166 if (y.getLeft(dataElement) != null) { 2167 y.getLeft(dataElement).setParent(y, dataElement); 2168 } 2169 2170 if (y.getRight(dataElement) != null) { 2171 y.getRight(dataElement).setParent(y, dataElement); 2172 } 2173 2174 x.swapColors(y, dataElement); 2175 2176 // Check if root changed 2177 if (rootNode[dataElement.ordinal()] == x) { 2178 rootNode[dataElement.ordinal()] = y; 2179 } else if (rootNode[dataElement.ordinal()] == y) { 2180 rootNode[dataElement.ordinal()] = x; 2181 } 2182 } 2183 2184 /** 2185 * Returns a string version of this Map in standard format. 2186 * 2187 * @return a standard format string version of the map 2188 */ 2189 @Override 2190 public String toString() { 2191 return this.doToString(KEY); 2192 } 2193 2194 /** 2195 * Returns a set view of the values contained in this map in key order. 2196 * The returned object can be cast to a Set. 2197 * <p> 2198 * The set is backed by the map, so changes to the map are reflected in 2199 * the set, and vice-versa. If the map is modified while an iteration over 2200 * the set is in progress, the results of the iteration are undefined. 2201 * <p> 2202 * The set supports element removal, which removes the corresponding mapping 2203 * from the map. It does not support the add or addAll operations. 2204 * 2205 * @return a set view of the values contained in this map. 2206 */ 2207 @Override 2208 public Set<V> values() { 2209 if (valuesSet == null) { 2210 valuesSet = new ValueView(KEY); 2211 } 2212 return valuesSet; 2213 } 2214 2215 /** 2216 * Serializes this object to an ObjectOutputStream. 2217 * 2218 * @param out the target ObjectOutputStream. 2219 * @throws IOException thrown when an I/O errors occur writing to the target stream. 2220 */ 2221 private void writeObject(final ObjectOutputStream out) throws IOException { 2222 out.defaultWriteObject(); 2223 out.writeInt(this.size()); 2224 for (final Entry<K, V> entry : entrySet()) { 2225 out.writeObject(entry.getKey()); 2226 out.writeObject(entry.getValue()); 2227 } 2228 } 2229 2230}