1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.collections4.bidimap;
18
19 import static org.apache.commons.collections4.bidimap.TreeBidiMap.DataElement.KEY;
20 import static org.apache.commons.collections4.bidimap.TreeBidiMap.DataElement.VALUE;
21
22 import java.io.IOException;
23 import java.io.ObjectInputStream;
24 import java.io.ObjectOutputStream;
25 import java.io.Serializable;
26 import java.util.AbstractSet;
27 import java.util.ConcurrentModificationException;
28 import java.util.Iterator;
29 import java.util.Map;
30 import java.util.NoSuchElementException;
31 import java.util.Objects;
32 import java.util.Set;
33
34 import org.apache.commons.collections4.KeyValue;
35 import org.apache.commons.collections4.MapIterator;
36 import org.apache.commons.collections4.OrderedBidiMap;
37 import org.apache.commons.collections4.OrderedIterator;
38 import org.apache.commons.collections4.OrderedMapIterator;
39 import org.apache.commons.collections4.iterators.EmptyOrderedMapIterator;
40 import org.apache.commons.collections4.keyvalue.UnmodifiableMapEntry;
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85 public class TreeBidiMap<K extends Comparable<K>, V extends Comparable<V>>
86 implements OrderedBidiMap<K, V>, Serializable {
87
88
89
90
91 abstract class AbstractView<E> extends AbstractSet<E> {
92
93
94 final DataElement orderType;
95
96
97
98
99
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
117
118 abstract class AbstractViewIterator {
119
120
121 private final DataElement orderType;
122
123 Node<K, V> lastReturnedNode;
124
125 private Node<K, V> nextNode;
126
127 private Node<K, V> previousNode;
128
129 private int expectedModifications;
130
131
132
133
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
205
206
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
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
259
260 final class Inverse implements OrderedBidiMap<V, K> {
261
262
263 private Set<V> inverseKeySet;
264
265 private Set<K> inverseValuesSet;
266
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
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
452
453 final class InverseViewMapEntryIterator extends AbstractViewIterator implements OrderedIterator<Map.Entry<V, K>> {
454
455
456
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
478
479 final class InverseViewMapIterator extends AbstractViewIterator implements OrderedMapIterator<V, K> {
480
481
482
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
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
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
564
565
566
567
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
582
583
584
585
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
593
594
595
596
597
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
624
625
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
638
639
640
641
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
653
654
655
656 @Override
657 public V getValue() {
658 return value;
659 }
660
661
662
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
675
676
677
678
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
691
692
693
694
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
707
708
709
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
721
722
723
724
725
726 private void setParent(final Node<K, V> node, final DataElement dataElement) {
727 parentNode[dataElement.ordinal()] = node;
728 }
729
730
731
732
733
734
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
746
747
748
749
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
758
759
760
761
762
763 private void swapColors(final Node<K, V> node, final DataElement dataElement) {
764
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
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
800
801 final class ViewMapEntryIterator extends AbstractViewIterator implements OrderedIterator<Map.Entry<K, V>> {
802
803
804
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
823
824 final class ViewMapIterator extends AbstractViewIterator implements OrderedMapIterator<K, V> {
825
826
827
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
871
872
873
874
875
876 private static void checkKey(final Object key) {
877 checkNonNullComparable(key, KEY);
878 }
879
880
881
882
883
884
885
886
887
888
889 private static void checkKeyAndValue(final Object key, final Object value) {
890 checkKey(key);
891 checkValue(value);
892 }
893
894
895
896
897
898
899
900
901
902
903
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
914
915
916
917
918
919 private static void checkValue(final Object value) {
920 checkNonNullComparable(value, VALUE);
921 }
922
923
924
925
926
927
928
929
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
937
938
939
940
941
942
943 private static boolean isBlack(final Node<?, ?> node, final DataElement dataElement) {
944 return node == null || node.isBlack(dataElement);
945 }
946
947
948
949
950
951
952
953
954
955 private static boolean isRed(final Node<?, ?> node, final DataElement dataElement) {
956 return node != null && node.isRed(dataElement);
957 }
958
959
960
961
962
963
964
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
974
975
976
977
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
1001
1002 @SuppressWarnings("unchecked")
1003 public TreeBidiMap() {
1004 rootNode = new Node[2];
1005 }
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015 public TreeBidiMap(final Map<? extends K, ? extends V> map) {
1016 this();
1017 putAll(map);
1018 }
1019
1020
1021
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
1034
1035
1036
1037
1038
1039
1040
1041
1042 @Override
1043 public boolean containsKey(final Object key) {
1044 checkKey(key);
1045 return lookupKey(key) != null;
1046 }
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058 @Override
1059 public boolean containsValue(final Object value) {
1060 checkValue(value);
1061 return lookupValue(value) != null;
1062 }
1063
1064
1065
1066
1067
1068
1069
1070
1071
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
1077 to.setBlack(dataElement);
1078 } else {
1079 to.copyColor(from, dataElement);
1080 }
1081 }
1082 }
1083
1084
1085
1086
1087
1088
1089
1090
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
1122
1123
1124
1125
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
1141
1142
1143
1144
1145 private void doPut(final K key, final V value) {
1146 checkKeyAndValue(key, value);
1147
1148
1149 doRemoveKey(key);
1150 doRemoveValue(value);
1151
1152 Node<K, V> node = rootNode[KEY.ordinal()];
1153 if (node == null) {
1154
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
1162 while (true) {
1163 final int cmp = compare(key, node.getKey());
1164
1165 if (cmp == 0) {
1166
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 {
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
1202
1203
1204
1205
1206 private void doRedBlackDelete(final Node<K, V> deletedNode) {
1207 for (final DataElement dataElement : DataElement.values()) {
1208
1209
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
1238 if (deletedNode.getParent(dataElement) == null) {
1239
1240
1241 rootNode[dataElement.ordinal()] = null;
1242 } else {
1243
1244
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
1266
1267
1268
1269
1270
1271
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
1349
1350
1351
1352
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
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
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
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
1437
1438
1439
1440
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
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
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
1491
1492
1493
1494
1495 @Override
1496 public boolean equals(final Object obj) {
1497 return this.doEquals(obj, KEY);
1498 }
1499
1500
1501
1502
1503
1504
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
1516
1517
1518
1519
1520
1521
1522
1523
1524
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
1535
1536
1537
1538
1539
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
1547
1548
1549
1550
1551
1552
1553
1554
1555
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
1566
1567
1568
1569
1570
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
1589
1590
1591
1592
1593
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
1601
1602
1603
1604
1605
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
1613
1614
1615
1616
1617
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
1631
1632 private void grow() {
1633 modify();
1634 nodeCount++;
1635 }
1636
1637
1638
1639
1640
1641
1642 @Override
1643 public int hashCode() {
1644 return this.doHashCode(KEY);
1645 }
1646
1647
1648
1649
1650
1651
1652
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 {
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
1688
1689
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
1701
1702
1703
1704 @Override
1705 public boolean isEmpty() {
1706 return nodeCount == 0;
1707 }
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
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
1731
1732
1733
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
1745
1746
1747
1748
1749
1750
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
1764
1765
1766
1767
1768
1769
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
1806
1807
1808
1809 private void modify() {
1810 modifications++;
1811 }
1812
1813
1814
1815
1816
1817
1818
1819
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
1827
1828 rval = leastNode(node.getRight(dataElement), dataElement);
1829 } else {
1830
1831
1832
1833
1834
1835
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
1850
1851
1852
1853
1854
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
1865
1866
1867
1868
1869
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
1877
1878 rval = greatestNode(node.getLeft(dataElement), dataElement);
1879 } else {
1880
1881
1882
1883
1884
1885
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
1900
1901
1902
1903
1904
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
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
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
1946
1947
1948
1949
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
1960
1961
1962
1963
1964
1965 @SuppressWarnings("unchecked")
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
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988 @Override
1989 public V remove(final Object key) {
1990 return doRemoveKey(key);
1991 }
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004 @Override
2005 public K removeValue(final Object value) {
2006 return doRemoveValue(value);
2007 }
2008
2009
2010
2011
2012
2013
2014
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
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
2040
2041
2042
2043
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
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
2068
2069 private void shrink() {
2070 modify();
2071 nodeCount--;
2072 }
2073
2074
2075
2076
2077
2078
2079 @Override
2080 public int size() {
2081 return nodeCount;
2082 }
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093 private void swapPosition(final Node<K, V> x, final Node<K, V> y, final DataElement dataElement) {
2094
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
2107 if (x == yFormerParent) {
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) {
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
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
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
2186
2187
2188
2189 @Override
2190 public String toString() {
2191 return this.doToString(KEY);
2192 }
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
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
2217
2218
2219
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 }