| 1 16 package org.apache.commons.collections; 17 18 import java.util.AbstractCollection ; 19 import java.util.AbstractMap ; 20 import java.util.AbstractSet ; 21 import java.util.Collection ; 22 import java.util.ConcurrentModificationException ; 23 import java.util.Iterator ; 24 import java.util.Map ; 25 import java.util.NoSuchElementException ; 26 import java.util.Set ; 27 28 106 public final class DoubleOrderedMap extends AbstractMap { 107 109 private static final int KEY = 0; 110 private static final int VALUE = 1; 111 private static final int SUM_OF_INDICES = KEY + VALUE; 112 private static final int FIRST_INDEX = 0; 113 private static final int NUMBER_OF_INDICES = 2; 114 private static final String [] dataName = new String [] { "key", "value" }; 115 116 private Node[] rootNode = new Node[] { null, null }; 117 private int nodeCount = 0; 118 private int modifications = 0; 119 private Set [] setOfKeys = new Set [] { null, null }; 120 private Set [] setOfEntries = new Set [] { null, null }; 121 private Collection [] collectionOfValues = new Collection [] { null, null }; 122 123 126 public DoubleOrderedMap() { 127 } 128 129 146 public DoubleOrderedMap(final Map map) 147 throws ClassCastException , NullPointerException , 148 IllegalArgumentException { 149 putAll(map); 150 } 151 152 165 public Object getKeyForValue(final Object value) 166 throws ClassCastException , NullPointerException { 167 return doGet((Comparable ) value, VALUE); 168 } 169 170 178 public Object removeValue(final Object value) { 179 return doRemove((Comparable ) value, VALUE); 180 } 181 182 201 public Set entrySetByValue() { 202 203 if (setOfEntries[VALUE] == null) { 204 setOfEntries[VALUE] = new AbstractSet () { 205 206 public Iterator iterator() { 207 208 return new DoubleOrderedMapIterator(VALUE) { 209 210 protected Object doGetNext() { 211 return lastReturnedNode; 212 } 213 }; 214 } 215 216 public boolean contains(Object o) { 217 218 if (!(o instanceof Map.Entry )) { 219 return false; 220 } 221 222 Map.Entry entry = (Map.Entry ) o; 223 Object key = entry.getKey(); 224 Node node = lookup((Comparable ) entry.getValue(), 225 VALUE); 226 227 return (node != null) && node.getData(KEY).equals(key); 228 } 229 230 public boolean remove(Object o) { 231 232 if (!(o instanceof Map.Entry )) { 233 return false; 234 } 235 236 Map.Entry entry = (Map.Entry ) o; 237 Object key = entry.getKey(); 238 Node node = lookup((Comparable ) entry.getValue(), 239 VALUE); 240 241 if ((node != null) && node.getData(KEY).equals(key)) { 242 doRedBlackDelete(node); 243 244 return true; 245 } 246 247 return false; 248 } 249 250 public int size() { 251 return DoubleOrderedMap.this.size(); 252 } 253 254 public void clear() { 255 DoubleOrderedMap.this.clear(); 256 } 257 }; 258 } 259 260 return setOfEntries[VALUE]; 261 } 262 263 281 public Set keySetByValue() { 282 283 if (setOfKeys[VALUE] == null) { 284 setOfKeys[VALUE] = new AbstractSet () { 285 286 public Iterator iterator() { 287 288 return new DoubleOrderedMapIterator(VALUE) { 289 290 protected Object doGetNext() { 291 return lastReturnedNode.getData(KEY); 292 } 293 }; 294 } 295 296 public int size() { 297 return DoubleOrderedMap.this.size(); 298 } 299 300 public boolean contains(Object o) { 301 return containsKey(o); 302 } 303 304 public boolean remove(Object o) { 305 306 int oldnodeCount = nodeCount; 307 308 DoubleOrderedMap.this.remove(o); 309 310 return nodeCount != oldnodeCount; 311 } 312 313 public void clear() { 314 DoubleOrderedMap.this.clear(); 315 } 316 }; 317 } 318 319 return setOfKeys[VALUE]; 320 } 321 322 340 public Collection valuesByValue() { 341 342 if (collectionOfValues[VALUE] == null) { 343 collectionOfValues[VALUE] = new AbstractCollection () { 344 345 public Iterator iterator() { 346 347 return new DoubleOrderedMapIterator(VALUE) { 348 349 protected Object doGetNext() { 350 return lastReturnedNode.getData(VALUE); 351 } 352 }; 353 } 354 355 public int size() { 356 return DoubleOrderedMap.this.size(); 357 } 358 359 public boolean contains(Object o) { 360 return containsValue(o); 361 } 362 363 public boolean remove(Object o) { 364 365 int oldnodeCount = nodeCount; 366 367 removeValue(o); 368 369 return nodeCount != oldnodeCount; 370 } 371 372 public boolean removeAll(Collection c) { 373 374 boolean modified = false; 375 Iterator iter = c.iterator(); 376 377 while (iter.hasNext()) { 378 if (removeValue(iter.next()) != null) { 379 modified = true; 380 } 381 } 382 383 return modified; 384 } 385 386 public void clear() { 387 DoubleOrderedMap.this.clear(); 388 } 389 }; 390 } 391 392 return collectionOfValues[VALUE]; 393 } 394 395 405 private Object doRemove(final Comparable o, final int index) { 406 407 Node node = lookup(o, index); 408 Object rval = null; 409 410 if (node != null) { 411 rval = node.getData(oppositeIndex(index)); 412 413 doRedBlackDelete(node); 414 } 415 416 return rval; 417 } 418 419 429 private Object doGet(final Comparable o, final int index) { 430 431 checkNonNullComparable(o, index); 432 433 Node node = lookup(o, index); 434 435 return ((node == null) 436 ? null 437 : node.getData(oppositeIndex(index))); 438 } 439 440 447 private int oppositeIndex(final int index) { 448 449 return SUM_OF_INDICES - index; 453 } 454 455 464 private Node lookup(final Comparable data, final int index) { 465 466 Node rval = null; 467 Node node = rootNode[index]; 468 469 while (node != null) { 470 int cmp = compare(data, node.getData(index)); 471 472 if (cmp == 0) { 473 rval = node; 474 475 break; 476 } else { 477 node = (cmp < 0) 478 ? node.getLeft(index) 479 : node.getRight(index); 480 } 481 } 482 483 return rval; 484 } 485 486 495 private static int compare(final Comparable o1, final Comparable o2) { 496 return o1.compareTo(o2); 497 } 498 499 509 private static Node leastNode(final Node node, final int index) { 510 511 Node rval = node; 512 513 if (rval != null) { 514 while (rval.getLeft(index) != null) { 515 rval = rval.getLeft(index); 516 } 517 } 518 519 return rval; 520 } 521 522 530 private Node nextGreater(final Node node, final int index) { 531 532 Node rval = null; 533 534 if (node == null) { 535 rval = null; 536 } else if (node.getRight(index) != null) { 537 538 rval = leastNode(node.getRight(index), index); 541 } else { 542 543 Node parent = node.getParent(index); 550 Node child = node; 551 552 while ((parent != null) && (child == parent.getRight(index))) { 553 child = parent; 554 parent = parent.getParent(index); 555 } 556 557 rval = parent; 558 } 559 560 return rval; 561 } 562 563 571 private static void copyColor(final Node from, final Node to, 572 final int index) { 573 574 if (to != null) { 575 if (from == null) { 576 577 to.setBlack(index); 579 } else { 580 to.copyColor(from, index); 581 } 582 } 583 } 584 585 592 private static boolean isRed(final Node node, final int index) { 593 594 return ((node == null) 595 ? false 596 : node.isRed(index)); 597 } 598 599 606 private static boolean isBlack(final Node node, final int index) { 607 608 return ((node == null) 609 ? true 610 : node.isBlack(index)); 611 } 612 613 619 private static void makeRed(final Node node, final int index) { 620 621 if (node != null) { 622 node.setRed(index); 623 } 624 } 625 626 632 private static void makeBlack(final Node node, final int index) { 633 634 if (node != null) { 635 node.setBlack(index); 636 } 637 } 638 639 646 private static Node getGrandParent(final Node node, final int index) { 647 return getParent(getParent(node, index), index); 648 } 649 650 657 private static Node getParent(final Node node, final int index) { 658 659 return ((node == null) 660 ? null 661 : node.getParent(index)); 662 } 663 664 671 private static Node getRightChild(final Node node, final int index) { 672 673 return (node == null) 674 ? null 675 : node.getRight(index); 676 } 677 678 685 private static Node getLeftChild(final Node node, final int index) { 686 687 return (node == null) 688 ? null 689 : node.getLeft(index); 690 } 691 692 703 private static boolean isLeftChild(final Node node, final int index) { 704 705 return (node == null) 706 ? true 707 : ((node.getParent(index) == null) 708 ? false 709 : (node == node.getParent(index).getLeft(index))); 710 } 711 712 723 private static boolean isRightChild(final Node node, final int index) { 724 725 return (node == null) 726 ? true 727 : ((node.getParent(index) == null) 728 ? false 729 : (node == node.getParent(index).getRight(index))); 730 } 731 732 738 private void rotateLeft(final Node node, final int index) { 739 740 Node rightChild = node.getRight(index); 741 742 node.setRight(rightChild.getLeft(index), index); 743 744 if (rightChild.getLeft(index) != null) { 745 rightChild.getLeft(index).setParent(node, index); 746 } 747 748 rightChild.setParent(node.getParent(index), index); 749 750 if (node.getParent(index) == null) { 751 752 rootNode[index] = rightChild; 754 } else if (node.getParent(index).getLeft(index) == node) { 755 node.getParent(index).setLeft(rightChild, index); 756 } else { 757 node.getParent(index).setRight(rightChild, index); 758 } 759 760 rightChild.setLeft(node, index); 761 node.setParent(rightChild, index); 762 } 763 764 770 private void rotateRight(final Node node, final int index) { 771 772 Node leftChild = node.getLeft(index); 773 774 node.setLeft(leftChild.getRight(index), index); 775 776 if (leftChild.getRight(index) != null) { 777 leftChild.getRight(index).setParent(node, index); 778 } 779 780 leftChild.setParent(node.getParent(index), index); 781 782 if (node.getParent(index) == null) { 783 784 rootNode[index] = leftChild; 786 } else if (node.getParent(index).getRight(index) == node) { 787 node.getParent(index).setRight(leftChild, index); 788 } else { 789 node.getParent(index).setLeft(leftChild, index); 790 } 791 792 leftChild.setRight(node, index); 793 node.setParent(leftChild, index); 794 } 795 796 803 private void doRedBlackInsert(final Node insertedNode, final int index) { 804 805 Node currentNode = insertedNode; 806 807 makeRed(currentNode, index); 808 809 while ((currentNode != null) && (currentNode != rootNode[index]) 810 && (isRed(currentNode.getParent(index), index))) { 811 if (isLeftChild(getParent(currentNode, index), index)) { 812 Node y = getRightChild(getGrandParent(currentNode, index), 813 index); 814 815 if (isRed(y, index)) { 816 makeBlack(getParent(currentNode, index), index); 817 makeBlack(y, index); 818 makeRed(getGrandParent(currentNode, index), index); 819 820 currentNode = getGrandParent(currentNode, index); 821 } else { 822 if (isRightChild(currentNode, index)) { 823 currentNode = getParent(currentNode, index); 824 825 rotateLeft(currentNode, index); 826 } 827 828 makeBlack(getParent(currentNode, index), index); 829 makeRed(getGrandParent(currentNode, index), index); 830 831 if (getGrandParent(currentNode, index) != null) { 832 rotateRight(getGrandParent(currentNode, index), 833 index); 834 } 835 } 836 } else { 837 838 Node y = getLeftChild(getGrandParent(currentNode, index), 840 index); 841 842 if (isRed(y, index)) { 843 makeBlack(getParent(currentNode, index), index); 844 makeBlack(y, index); 845 makeRed(getGrandParent(currentNode, index), index); 846 847 currentNode = getGrandParent(currentNode, index); 848 } else { 849 if (isLeftChild(currentNode, index)) { 850 currentNode = getParent(currentNode, index); 851 852 rotateRight(currentNode, index); 853 } 854 855 makeBlack(getParent(currentNode, index), index); 856 makeRed(getGrandParent(currentNode, index), index); 857 858 if (getGrandParent(currentNode, index) != null) { 859 rotateLeft(getGrandParent(currentNode, index), index); 860 } 861 } 862 } 863 } 864 865 makeBlack(rootNode[index], index); 866 } 867 868 874 private void doRedBlackDelete(final Node deletedNode) { 875 876 for (int index = FIRST_INDEX; index < NUMBER_OF_INDICES; index++) { 877 878 if ((deletedNode.getLeft(index) != null) 881 && (deletedNode.getRight(index) != null)) { 882 swapPosition(nextGreater(deletedNode, index), deletedNode, 883 index); 884 } 885 886 Node replacement = ((deletedNode.getLeft(index) != null) 887 ? deletedNode.getLeft(index) 888 : deletedNode.getRight(index)); 889 890 if (replacement != null) { 891 replacement.setParent(deletedNode.getParent(index), index); 892 893 if (deletedNode.getParent(index) == null) { 894 rootNode[index] = replacement; 895 } else if (deletedNode 896 == deletedNode.getParent(index).getLeft(index)) { 897 deletedNode.getParent(index).setLeft(replacement, index); 898 } else { 899 deletedNode.getParent(index).setRight(replacement, index); 900 } 901 902 deletedNode.setLeft(null, index); 903 deletedNode.setRight(null, index); 904 deletedNode.setParent(null, index); 905 906 if (isBlack(deletedNode, index)) { 907 doRedBlackDeleteFixup(replacement, index); 908 } 909 } else { 910
|