1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package org.millscript.commons.util.map;
22
23 import java.io.IOException;
24 import java.io.ObjectInputStream;
25 import java.io.ObjectOutputStream;
26 import java.io.Serializable;
27
28 import org.millscript.commons.alert.alerts.Fault;
29 import org.millscript.commons.util.IList;
30 import org.millscript.commons.util.IMap;
31 import org.millscript.commons.util.ListIterator;
32 import org.millscript.commons.util.MapIterator;
33 import org.millscript.commons.util.Maplet;
34 import org.millscript.commons.util.alerts.ListIndexOutOfBoundsAlert;
35 import org.millscript.commons.util.alerts.NoSuchKeyInMapAlert;
36 import org.millscript.commons.util.iterator.AbstractListIterator;
37 import org.millscript.commons.util.iterator.AbstractMapIterator;
38 import org.millscript.commons.util.iterator.ArrayListIterator;
39 import org.millscript.commons.util.list.AbstractIList;
40 import org.millscript.commons.util.list.IArrayList;
41
42 /**
43 *
44 */
45 public class EBinaryTreeMap< K extends Comparable< K >, V > extends AbstractEMap< K, V > implements Cloneable, Serializable {
46
47 /**
48 * This is the ID from the release 0.1.0 for future compatibility.
49 */
50 private static final long serialVersionUID = 5434674165103600680L;
51
52 public static class Node< K extends Comparable< K >, V > implements Maplet< K, V > {
53
54 /**
55 * The height of the tree at this point, i.e. the largest numer of
56 * child nodes to a leaf. A short allows for a maximum height of 32767
57 * nodes(without trying to use the negatives) allowing around 500
58 * million entries in the map.
59 */
60 private short height;
61
62 /**
63 * The size of the tree at this point, i.e. the number of nodes
64 * including this one and its children.
65 */
66 int size;
67
68 /**
69 * The maplet key stored at this node.
70 */
71 final K key;
72
73 /**
74 * The left child node.
75 */
76 Node< K, V > left;
77
78 /**
79 * The parent node.
80 */
81 Node< K, V > parent;
82
83 /**
84 * The right child node.
85 */
86 Node< K, V > right;
87
88 /**
89 * The maplet value stored at this node.
90 */
91 V value;
92
93 public Node( final Node< K, V > p, final K k, final V v ) {
94
95 this.height = 0;
96 this.key = k;
97 this.parent = p;
98
99 this.size = 1;
100 this.value = v;
101 }
102
103 public Node( final Node< K, V > p, final K[] keys, final V[] values, final int first, final int last ) {
104 this.parent = p;
105
106
107
108
109
110
111
112
113
114
115
116 final int zeroBasedCentralIndex = ( last + first - 1 ) / 2;
117 this.key = (K) keys[ zeroBasedCentralIndex ];
118 this.value = (V) values[ zeroBasedCentralIndex ];
119
120
121
122
123
124 if ( zeroBasedCentralIndex >= first ) {
125
126 this.left = new Node< K, V >( this, keys, values, first, zeroBasedCentralIndex );
127 }
128
129
130 final int lastRight = zeroBasedCentralIndex + 2;
131
132 if ( lastRight <= last ) {
133
134 this.right = new Node< K, V >( this, keys, values, lastRight, last );
135 }
136
137 this.updateSize();
138 }
139
140 public Node< K, V > deepCopy() {
141 final Node< K, V > copy = new Node< K, V >( this.parent, this.key, this.value );
142 if ( this.left != null ) {
143 copy.left = this.left.deepCopy();
144 }
145 if ( this.right != null ) {
146 copy.right = this.right.deepCopy();
147 }
148 copy.updateSize();
149 return copy;
150 }
151
152 public Node< K, V > getLeftmost() {
153 Node< K, V > leftmost = this;
154 while ( leftmost.left != null ) {
155 leftmost = leftmost.left;
156 }
157 return leftmost;
158 }
159
160 public Node< K, V > getNextInSequence() {
161
162 if ( this.right == null ) {
163 if ( this.parent == null ) {
164
165
166 return null;
167 } else {
168
169
170 Node< K, V > nextNode = this.parent;
171
172
173 if ( this == this.parent.right ) {
174
175
176
177 while ( nextNode.parent != null && nextNode == nextNode.parent.right ) {
178 nextNode = nextNode.parent;
179 }
180 nextNode = nextNode.parent;
181 }
182 return nextNode;
183 }
184 } else {
185 Node< K, V > nextNode = this.right;
186 while ( nextNode.left != null ) {
187 nextNode = nextNode.left;
188 }
189 return nextNode;
190 }
191 }
192
193 public K getKey() {
194 return this.key;
195 }
196
197 public V getValue() {
198 return this.value;
199 }
200
201 public void insertPushLeft( final EBinaryTreeMap< K, V > map, final K k, final V v ) {
202
203 final Node< K, V > replacementNode = new Node< K, V >( this.parent, k, v );
204 replacementNode.left = this;
205 replacementNode.right = this.right;
206
207 if ( this.parent == null ) {
208 map.root = replacementNode;
209 } else if ( this == this.parent.left ) {
210 this.parent.left = replacementNode;
211 } else {
212 this.parent.right = replacementNode;
213 }
214 this.parent = replacementNode;
215 this.right.parent = replacementNode;
216 this.right = null;
217
218
219 this.updateSize();
220
221 replacementNode.updateSize();
222 }
223
224 public void insertPushRight( final EBinaryTreeMap< K, V > map, final K k, final V v ) {
225
226 final Node< K, V > replacementNode = new Node< K, V >( this.parent, k, v );
227 replacementNode.left = this.left;
228 replacementNode.right = this;
229
230 if ( this.parent == null ) {
231 map.root = replacementNode;
232 } else if ( this == this.parent.left ) {
233 this.parent.left = replacementNode;
234 } else {
235 this.parent.right = replacementNode;
236 }
237 this.parent = replacementNode;
238 this.left.parent = replacementNode;
239 this.left = null;
240
241
242 this.updateSize();
243
244 replacementNode.updateSize();
245 }
246
247 protected Node< K, V > remove( final EBinaryTreeMap< K, V > map ) {
248 if ( this.left == null ) {
249 if ( this.parent == null ) {
250
251 map.root = this.right;
252 } else if ( this == this.parent.left ) {
253 this.parent.left = this.right;
254 } else {
255 this.parent.right = this.right;
256 }
257 if ( this.right == null ) {
258 return this.parent;
259 } else {
260 this.right.parent = this.parent;
261 return this.right;
262 }
263 } else if ( this.right == null ) {
264
265
266 if ( this.parent == null ) {
267
268 map.root = this.left;
269 } else if ( this == this.parent.left ) {
270 this.parent.left = this.left;
271 } else {
272 this.parent.right = this.left;
273 }
274 if ( this.left == null ) {
275 return this.parent;
276 } else {
277 this.left.parent = this.parent;
278 return this.left;
279 }
280 } else if ( Math.random() < 0.5d ) {
281
282
283
284 Node< K, V > replacement = this.right;
285 while ( replacement.left != null ) {
286 replacement = replacement.left;
287 }
288 if ( this.parent == null ) {
289
290 map.root = replacement;
291 } else if ( this == this.parent.left ) {
292 this.parent.left = replacement;
293 } else {
294 this.parent.right = replacement;
295 }
296 if ( replacement == this.right ) {
297
298
299 replacement.left = this.left;
300 this.left.parent = replacement;
301 replacement.parent = this.parent;
302 } else {
303
304
305 replacement.left = this.left;
306 this.left.parent = replacement;
307
308 replacement.parent.left = replacement.right;
309 if ( replacement.right != null ) {
310 replacement.right.parent = replacement.parent;
311 }
312 Node< K, V > fixsizeFromHere = replacement.parent;
313 replacement.parent = this.parent;
314 replacement.right = this.right;
315 this.right.parent = replacement;
316 for ( ; fixsizeFromHere != null; fixsizeFromHere = fixsizeFromHere.parent ) {
317 fixsizeFromHere.updateSize();
318 }
319 }
320 return replacement;
321 } else {
322
323
324
325 Node< K, V > replacement = this.left;
326 while ( replacement.right != null ) {
327 replacement = replacement.right;
328 }
329 if ( this.parent == null ) {
330
331 map.root = replacement;
332 } else if ( this == this.parent.left ) {
333 this.parent.left = replacement;
334 } else {
335 this.parent.right = replacement;
336 }
337 if ( replacement == this.left ) {
338
339
340 replacement.right = this.right;
341 this.right.parent = replacement;
342 replacement.parent = this.parent;
343 } else {
344
345
346 replacement.right = this.right;
347 this.right.parent = replacement;
348
349 replacement.parent.right = replacement.left;
350 if ( replacement.left != null ) {
351 replacement.left.parent = replacement.parent;
352 }
353 Node< K, V > fixsizeFromHere = replacement.parent;
354 replacement.parent = this.parent;
355 replacement.left = this.left;
356 this.left.parent = replacement;
357 for ( ; fixsizeFromHere != null; fixsizeFromHere = fixsizeFromHere.parent ) {
358 fixsizeFromHere.updateSize();
359 }
360 }
361 return replacement;
362 }
363 }
364
365 public void rotateLeft( final EBinaryTreeMap< K, V > map ) {
366
367 this.right.parent = this.parent;
368
369
370 if ( this.parent == null ) {
371 map.root = this.right;
372 } else {
373 if ( this == this.parent.left ) {
374 this.parent.left = this.right;
375 } else {
376 this.parent.right = this.right;
377 }
378 }
379
380 this.parent = this.right;
381
382 final Node< K, V > onTheMove = this.right.left;
383
384 this.right.left = this;
385
386
387 this.right = onTheMove;
388 if ( onTheMove != null ) {
389 onTheMove.parent = this;
390 }
391
392 this.updateSize();
393 this.parent.updateSize();
394 }
395
396 public void rotateRight( final EBinaryTreeMap< K, V > map ) {
397
398 this.left.parent = this.parent;
399
400
401 if ( this.parent == null ) {
402 map.root = this.left;
403 } else {
404 if ( this == this.parent.left ) {
405 this.parent.left = this.left;
406 } else {
407 this.parent.right = this.left;
408 }
409 }
410
411 this.parent = this.left;
412
413 final Node< K, V > onTheMove = this.left.right;
414
415 this.left.right = this;
416
417
418 this.left = onTheMove;
419 if ( onTheMove != null ) {
420 onTheMove.parent = this;
421 }
422
423 this.updateSize();
424 this.parent.updateSize();
425 }
426
427 protected void updateSize() {
428 if ( this.left == null ) {
429 if ( this.right == null ) {
430 this.size = 1;
431 } else {
432 this.size = 1 + this.right.size;
433 }
434 } else {
435 if ( this.right == null ) {
436 this.size = 1 + this.left.size;
437 } else {
438 this.size = 1 + this.left.size + this.right.size;
439 }
440 }
441 }
442
443 }
444
445 public static class NodeIterator< K extends Comparable< K >, V > extends AbstractMapIterator< K, V > {
446
447 /**
448 * The current node in the iteration.
449 */
450 private Node< K, V > currentNode;
451
452 /**
453 * The next node in the iteration, if this is null
454 */
455 private Node< K, V > nextNode;
456
457 /**
458 * Constructs a new binary tree map iterator to iterate over the specified
459 * node tree.
460 *
461 * @param rootNode the root node in the tree to iterate over
462 * @param share if <code>true</code> the specified node tree will be
463 * shared otherwise the array will be copied.
464 */
465 public NodeIterator( final Node< K, V > rootNode, final boolean share ) {
466 if ( rootNode != null ) {
467 if ( share ) {
468 this.nextNode = rootNode.getLeftmost();
469 } else {
470 this.nextNode = rootNode.deepCopy().getLeftmost();
471 }
472 }
473 }
474
475 /**
476 * @see org.millscript.commons.util.iterator.AbstractMapIterator#advance()
477 */
478 @Override
479 protected void advance() {
480
481 this.checkNext();
482
483 this.currentNode = this.nextNode;
484 this.nextNode = null;
485 }
486
487 /**
488 * Checks that the next maplet field is populated with the next maplet
489 * if one is available.
490 */
491 private void checkNext() {
492 if ( this.nextNode == null && this.currentNode != null ) {
493 this.nextNode = this.currentNode.getNextInSequence();
494 }
495 }
496
497 /**
498 * @see org.millscript.commons.util.iterator.AbstractMapIterator#getKey()
499 */
500 @Override
501 protected K getKey() {
502 return this.currentNode.key;
503 }
504
505 /**
506 * @see org.millscript.commons.util.iterator.AbstractMapIterator#getMaplet()
507 */
508 @Override
509 protected Maplet< K, V > getMaplet() {
510 return this.currentNode;
511 }
512
513 /**
514 * @see org.millscript.commons.util.iterator.AbstractMapIterator#getValue()
515 */
516 @Override
517 protected V getValue() {
518 return this.currentNode.value;
519 }
520
521 /**
522 * @see org.millscript.commons.util.MapIterator#hasNext()
523 */
524 public boolean hasNext() {
525 this.checkNext();
526 return this.nextNode != null;
527 }
528
529 /**
530 * @see org.millscript.commons.util.iterator.AbstractMapIterator#outOfBounds()
531 */
532 @Override
533 protected boolean outOfBounds() {
534 return this.currentNode == null;
535 }
536
537 }
538
539 public static class NodeKeyIterator< K extends Comparable< K > > extends NodeXIterator< K > {
540
541 /**
542 * Constructs a new binary tree map iterator to iterate over the specified
543 * node tree.
544 *
545 * @param node any node in the leftmost branch of the backing store
546 * tree
547 * @param num the number of elements in this iteration
548 */
549 protected NodeKeyIterator( final Node< ?, ? > node, final int num ) {
550 super( node, num );
551 }
552
553 /**
554 * @see org.millscript.commons.util.map.EBinaryTreeMap.NodeXIterator#getAppropriateNodePart(org.millscript.commons.util.map.EBinaryTreeMap.Node)
555 */
556 @Override
557 @SuppressWarnings( "unchecked" )
558 K getAppropriateNodePart( final Node< ?, ? > node ) {
559 return (K) node.getKey();
560 }
561
562 }
563
564 public static class NodeKeyList< K extends Comparable< K > > extends NodeXList< K > {
565
566 /**
567 * Constructs a new immutable list of the keys in the specified node
568 * tree.
569 *
570 * @param node any node in the leftmost branch of the backing store
571 * tree
572 * @param start the index(one based, inclusive) to start iterating from
573 * @param end the index(one based, inclusive) to stop iterating at
574 */
575 protected NodeKeyList( final Node< ?, ? > node, final int start, final int end ) {
576 super( node, start, end );
577 }
578
579 /**
580 * @see org.millscript.commons.util.map.EBinaryTreeMap.NodeXList#getAppropriateNodePart(org.millscript.commons.util.map.EBinaryTreeMap.Node)
581 */
582 @Override
583 @SuppressWarnings( "unchecked" )
584 K getAppropriateNodePart( final Node< ?, ? > node ) {
585 return (K) node.getKey();
586 }
587
588 /**
589 * @see org.millscript.commons.util.map.EBinaryTreeMap.NodeXList#sharedIterator()
590 */
591 @Override
592 public ListIterator< K > sharedIterator() {
593 return new NodeKeyIterator< K >(
594 this.firstNode,
595 this.size
596 );
597 }
598
599 /**
600 * @see org.millscript.commons.util.map.EBinaryTreeMap.NodeXList#sharedSlice(int, int)
601 */
602 @Override IList< K > sharedSlice( final int first, final int last ) {
603 return new NodeKeyList< K >(
604 this.firstNode,
605 this.firstIndex + first - 1,
606 this.firstIndex + last - 1
607 );
608 }
609
610 }
611
612 public static class NodeMapletIterator< K extends Comparable< K >, V > extends NodeXIterator< Maplet< K, V > > {
613
614 /**
615 * Constructs a new binary tree map iterator to iterate over the specified
616 * node tree.
617 *
618 * @param node any node in the leftmost branch of the backing store
619 * tree
620 * @param num the number of elements in this iteration
621 */
622 protected NodeMapletIterator( final Node< ?, ? > node, final int num ) {
623 super( node, num );
624 }
625
626 /**
627 * @see org.millscript.commons.util.map.EBinaryTreeMap.NodeXIterator#getAppropriateNodePart(org.millscript.commons.util.map.EBinaryTreeMap.Node)
628 */
629 @Override
630 @SuppressWarnings( "unchecked" )
631 Maplet< K, V > getAppropriateNodePart( final Node< ?, ? > node ) {
632 return (Maplet< K, V >) node;
633 }
634
635 }
636
637 public static class NodeMapletList< K extends Comparable< K >, V > extends NodeXList< Maplet< K, V > > {
638
639 /**
640 * Constructs a new immutable list of the maplets in the specified node
641 * tree.
642 *
643 * @param node any node in the leftmost branch of the backing store
644 * tree
645 * @param start the index(one based, inclusive) to start iterating from
646 * @param end the index(one based, inclusive) to stop iterating at
647 */
648 protected NodeMapletList( final Node< ?, ? > node, final int start, final int end ) {
649 super( node, start, end );
650 }
651
652 /**
653 * @see org.millscript.commons.util.map.EBinaryTreeMap.NodeXList#getAppropriateNodePart(org.millscript.commons.util.map.EBinaryTreeMap.Node)
654 */
655 @Override
656 @SuppressWarnings( "unchecked" )
657 Maplet< K, V > getAppropriateNodePart( final Node< ?, ? > node ) {
658 return (Maplet<K, V>) node;
659 }
660
661 /**
662 * @see org.millscript.commons.util.map.EBinaryTreeMap.NodeXList#sharedIterator()
663 */
664 @Override
665 public ListIterator< Maplet< K, V > > sharedIterator() {
666 return new NodeMapletIterator< K, V >(
667 this.firstNode,
668 this.size
669 );
670 }
671
672 /**
673 * @see org.millscript.commons.util.map.EBinaryTreeMap.NodeXList#sharedSlice(int, int)
674 */
675 @Override
676 IList< Maplet< K, V > > sharedSlice( final int first, final int last ) {
677 return new NodeMapletList< K, V >(
678 this.firstNode,
679 this.firstIndex + first - 1,
680 this.firstIndex + last - 1
681 );
682 }
683
684 }
685
686 public static class NodeValueIterator< V > extends NodeXIterator< V > {
687
688 /**
689 * Constructs a new binary tree map iterator to iterate over the specified
690 * node tree.
691 *
692 * @param node any node in the leftmost branch of the backing store
693 * tree
694 * @param num the number of elements in this iteration
695 */
696 protected NodeValueIterator( final Node< ?, ? > node, final int num ) {
697 super( node, num );
698 }
699
700 /**
701 * @see org.millscript.commons.util.map.EBinaryTreeMap.NodeXIterator#getAppropriateNodePart(org.millscript.commons.util.map.EBinaryTreeMap.Node)
702 */
703 @Override
704 @SuppressWarnings( "unchecked" )
705 V getAppropriateNodePart( final Node< ?, ? > node ) {
706 return (V) node.getValue();
707 }
708
709 }
710
711 public static class NodeValueList< V > extends NodeXList< V > {
712
713 /**
714 * Constructs a new immutable list of the values in the specified node
715 * tree.
716 *
717 * @param node any node in the leftmost branch of the backing store
718 * tree
719 * @param start the index(one based, inclusive) to start iterating from
720 * @param end the index(one based, inclusive) to stop iterating at
721 */
722 protected NodeValueList( final Node< ?, ? > node, final int start, final int end ) {
723 super( node, start, end );
724 }
725
726 /**
727 * @see org.millscript.commons.util.map.EBinaryTreeMap.NodeXList#getAppropriateNodePart(org.millscript.commons.util.map.EBinaryTreeMap.Node)
728 */
729 @Override
730 @SuppressWarnings( "unchecked" )
731 V getAppropriateNodePart( final Node< ?, ? > node ) {
732 return (V) node.getValue();
733 }
734
735 /**
736 * @see org.millscript.commons.util.map.EBinaryTreeMap.NodeXList#sharedIterator()
737 */
738 @Override
739 public ListIterator< V > sharedIterator() {
740 return new NodeValueIterator< V >(
741 this.firstNode,
742 this.size
743 );
744 }
745
746 /**
747 * @see org.millscript.commons.util.map.EBinaryTreeMap.NodeXList#sharedSlice(int, int)
748 */
749 @Override
750 IList< V > sharedSlice( final int first, final int last ) {
751 return new NodeValueList< V >(
752 this.firstNode,
753 this.firstIndex + first - 1,
754 this.firstIndex + last - 1
755 );
756 }
757
758 }
759
760 public abstract static class NodeXIterator< E > extends AbstractListIterator< E > {
761
762 /**
763 * The current node in the iteration.
764 */
765 private Node< ?, ? > currentNode;
766
767 /**
768 * The next node in the iteration, if this is null
769 */
770 private Node< ?, ? > nextNode;
771
772 /**
773 * The list size.
774 */
775 private final int size;
776
777 /**
778 * Constructs a new binary tree map iterator to iterate over the specified
779 * node tree.
780 *
781 * @param node any node in the leftmost branch of the backing store
782 * tree
783 * @param num the number of elements in this iteration
784 */
785 protected NodeXIterator( final Node< ?, ? > node, final int num ) {
786 if ( num <= 0 ) {
787 this.nextNode = null;
788 this.size = 0;
789 } else {
790 this.nextNode = node;
791 this.size = num;
792 }
793 }
794
795 /**
796 * @see org.millscript.commons.util.iterator.AbstractMapIterator#advance()
797 */
798 @Override
799 protected void advance() {
800
801 super.advance();
802 this.currentNode = this.nextNode;
803
804
805 if ( super.position == this.size ) {
806 this.nextNode = null;
807 } else if ( this.nextNode != null ) {
808 this.nextNode = this.currentNode.getNextInSequence();
809 }
810 }
811
812 /**
813 * Returns the appropriate part of the specified node for this list.
814 *
815 * @param node the node to get the appropriate part from
816 * @return the appropriate part of the specified node
817 */
818 abstract E getAppropriateNodePart( Node< ?, ? > node );
819
820 /**
821 * @see org.millscript.commons.util.iterator.AbstractMapIterator#getValue()
822 */
823 @Override
824 protected E getValue() {
825 return this.getAppropriateNodePart( this.currentNode );
826 }
827
828 /**
829 * @see org.millscript.commons.util.MapIterator#hasNext()
830 */
831 public boolean hasNext() {
832 return this.nextNode != null;
833 }
834
835 /**
836 * @see org.millscript.commons.util.iterator.AbstractMapIterator#outOfBounds()
837 */
838 @Override
839 protected boolean outOfBounds() {
840 return this.currentNode == null;
841 }
842
843 }
844
845 public abstract static class NodeXList< E > extends AbstractIList< E > {
846
847 /**
848 * The index of the first element.
849 */
850 final int firstIndex;
851
852 /**
853 * The first node in the list.
854 */
855 final Node< ?, ? > firstNode;
856
857 /**
858 * The list size.
859 */
860 final int size;
861
862 /**
863 * Constructs a new immutable list backed by the specified node tree.
864 *
865 * @param node any node in the leftmost branch of the backing store
866 * tree
867 * @param start the index(one based, inclusive) to start iterating from
868 * @param end the index(one based, inclusive) to stop iterating at
869 */
870 protected NodeXList( final Node< ?, ? > node, final int start, final int end ) {
871 this.firstIndex = start;
872 if ( start > end ) {
873 this.firstNode = null;
874 this.size = 0;
875 } else if ( end - start + 1 > node.size ) {
876 throw new ListIndexOutOfBoundsAlert(
877 "Requested list exceeds bounds of specified node tree"
878 ).culprit(
879 "first element index",
880 start
881 ).culprit(
882 "last element index",
883 end
884 ).decorate( node ).mishap();
885 } else {
886 Node< ?, ? > current = node.getLeftmost();
887 int outerListCount = 1;
888
889 for ( ; outerListCount < start; outerListCount++ ) {
890 current = current.getNextInSequence();
891 }
892 this.firstNode = current;
893 this.size = end - start + 1;
894 }
895 }
896
897 /**
898 * @see org.millscript.commons.util.list.AbstractIList#doGet(int)
899 */
900 @Override
901 protected E doGet( final int pos ) {
902 int currentPos = 1;
903 for ( Node< ?, ? > current = this.firstNode; current != null; current = current.getNextInSequence() ) {
904 if ( pos == currentPos++ ) {
905 return this.getAppropriateNodePart( current );
906 }
907 }
908 throw new Fault(
909 "Specified position is neither out of bounds or within the list!"
910 ).culprit( "index", pos ).decorate( this ).mishap();
911 }
912
913 /**
914 * @see org.millscript.commons.util.list.AbstractIList#doSlice(int, int, boolean)
915 */
916 @Override
917 @SuppressWarnings( "unchecked" )
918 protected IList< E > doSlice( final int first, final int last, final boolean share ) {
919 if ( share ) {
920 return this.sharedSlice( first, last );
921 } else {
922
923 final E[] objects = (E[]) new Object[ first - last + 1 ];
924 Node< ?, ? > current = this.firstNode;
925 int outerListCount = 1;
926
927 for ( ; outerListCount <= first; outerListCount++ ) {
928 current = current.getNextInSequence();
929 }
930
931 int newArrayPos = 0;
932 for ( ; current != null && outerListCount <= last; current = current.getNextInSequence(), outerListCount++ ) {
933 objects[ newArrayPos++ ] = this.getAppropriateNodePart( current );
934 }
935 return new IArrayList< E >( objects, true );
936 }
937 }
938
939 /**
940 * Returns the appropriate part of the specified node for this list.
941 *
942 * @param node the node to get the appropriate part from
943 * @return the appropriate part of the specified node
944 */
945 abstract E getAppropriateNodePart( Node< ?, ? > node );
946
947 /**
948 * @see org.millscript.commons.util.IList#indexOf(java.lang.Object)
949 */
950 public int indexOf( final E value ) {
951 int currentPos = 1;
952 for ( Node< ?, ? > current = this.firstNode; current != null; current = current.getNextInSequence() ) {
953 if ( value == null ? this.getAppropriateNodePart( current ) == null : value.equals( this.getAppropriateNodePart( current ) ) ) {
954 return currentPos;
955 }
956 }
957 return 0;
958 }
959
960 /**
961 * @see org.millscript.commons.util.IMap#iterator(boolean)
962 */
963 @SuppressWarnings( "unchecked" )
964 public ListIterator< E > iterator( final boolean share ) {
965 if ( share ) {
966 return this.sharedIterator();
967 } else {
968 final E[] objects = (E[]) new Object[ this.size() ];
969 Node< ?, ? > current = this.firstNode;
970 for ( int i = 0; current != null; i++, current = current.getNextInSequence() ) {
971 objects[ i ] = this.getAppropriateNodePart( current );
972 }
973 return new ArrayListIterator< E >( objects, true );
974 }
975 }
976
977 /**
978 * Returns a list iterator which shares backing store with this list.
979 *
980 * @return a list iterator which shares this lists backing store
981 */
982 abstract ListIterator< E > sharedIterator();
983
984 /**
985 * Returns a slice of this list which shares backing store with this
986 * list.
987 *
988 * @param first the index(one based) of the first element in the slice
989 * @param last the index(one based) of the last element in the slice
990 * @return a slice of this list which shares this lists backing store
991 */
992 abstract IList< E > sharedSlice( int first, int last );
993
994 /**
995 * @see org.millscript.commons.util.IMap#size()
996 */
997 public int size() {
998 return this.size;
999 }
1000
1001 }
1002
1003
1004 /**
1005 * The root node in the tree.
1006 */
1007 transient Node< K, V > root;
1008
1009 /**
1010 * Constructs a new, emtpy extensible scapegoat tree map.
1011 */
1012 public EBinaryTreeMap() {
1013 }
1014
1015 /**
1016 * Constructs a new extensible scapegoat tree map which contains all the
1017 * mappings from the specified map.
1018 *
1019 * @param map the <code>Map</code> to copy mappings from
1020 */
1021 public EBinaryTreeMap( final IMap< K, V > map ) {
1022 if ( map.size() != 0 ) {
1023 final MapIterator< K, V > it = map.iterator( true );
1024 while ( it.hasNext() ) {
1025 this.insert( it.nextKey(), it.currentValue() );
1026 }
1027 }
1028 }
1029
1030 /**
1031 * @see java.lang.Object#clone()
1032 */
1033 @Override
1034 @SuppressWarnings( "unchecked" )
1035 public Object clone() throws CloneNotSupportedException {
1036 final EBinaryTreeMap< K, V > map = (EBinaryTreeMap< K, V >) super.clone();
1037 map.root = this.root.deepCopy();
1038 return map;
1039 }
1040
1041 protected int compare( final K a, final K b ) {
1042
1043
1044 if ( a == null ) {
1045 if ( b == null ) {
1046 return 0;
1047 } else {
1048 return Integer.MAX_VALUE;
1049 }
1050 } else {
1051 if ( b == null ) {
1052 return Integer.MIN_VALUE;
1053 }
1054 }
1055 final Class ca = a.getClass();
1056 final Class cb = b.getClass();
1057 if ( ca == cb ) {
1058
1059
1060 return a.compareTo( b );
1061 } else {
1062
1063
1064
1065
1066
1067 return ca.getName().compareTo( cb.getName() );
1068 }
1069 }
1070
1071 /**
1072 * @see org.millscript.commons.util.IMap#contains(java.lang.Object, java.lang.Object)
1073 */
1074 public boolean contains( final K key, final V value ) {
1075 if ( this.root != null ) {
1076 Node< K, V > current = this.root;
1077 while ( current != null ) {
1078 final int comp = this.compare( key, current.key );
1079 if ( comp == 0 ) {
1080
1081 return value == null ? current.value == null
1082 : value.equals( current.value );
1083 } else if ( comp < 0 ) {
1084
1085 current = current.left;
1086 } else {
1087
1088 current = current.right;
1089 }
1090 }
1091 }
1092 return false;
1093 }
1094
1095 /**
1096 * @see org.millscript.commons.util.IMap#containsKey(java.lang.Object)
1097 */
1098 public boolean containsKey( final K key ) {
1099 if ( this.root != null ) {
1100 Node< K, V > current = this.root;
1101 while ( current != null ) {
1102 final int comp = this.compare( key, current.key );
1103 if ( comp == 0 ) {
1104
1105 return true;
1106 } else if ( comp < 0 ) {
1107
1108 current = current.left;
1109 } else {
1110
1111 current = current.right;
1112 }
1113 }
1114 }
1115 return false;
1116 }
1117
1118 /**
1119 * @see org.millscript.commons.util.IMap#containsValue(java.lang.Object)
1120 */
1121 public boolean containsValue( final V value ) {
1122 if ( this.root != null ) {
1123 Node< K, V > current = this.root.getLeftmost();
1124 while ( current != null ) {
1125 if ( value == null ? current.value == null : value.equals( current.value ) ) {
1126 return true;
1127 } else {
1128 current = current.getNextInSequence();
1129 }
1130 }
1131 }
1132 return false;
1133 }
1134
1135 /**
1136 * @see org.millscript.commons.util.IMap#get(java.lang.Object)
1137 */
1138 public V get( final K key ) {
1139 if ( this.root != null ) {
1140 Node< K, V > current = this.root;
1141 while ( current != null ) {
1142 final int comp = this.compare( key, current.key );
1143 if ( comp == 0 ) {
1144
1145 return current.value;
1146 } else if ( comp < 0 ) {
1147
1148 current = current.left;
1149 } else {
1150
1151 current = current.right;
1152 }
1153 }
1154 }
1155 return this.getDefault().get( this, key );
1156 }
1157
1158 /**
1159 * @see org.millscript.commons.util.EMap#insert(java.lang.Object, java.lang.Object)
1160 */
1161 public void insert( final K key, final V value ) {
1162 if ( this.root == null ) {
1163 this.root = new Node< K, V >( null, key, value );
1164 } else {
1165 Node< K, V > current = this.root;
1166 while ( current != null ) {
1167 final int comp = this.compare( key, current.key );
1168 if ( comp == 0 ) {
1169
1170
1171
1172 current.value = value;
1173 break;
1174 } else if ( comp < 0 ) {
1175
1176 if ( current.left == null ) {
1177
1178
1179 if ( current.parent == null ) {
1180
1181
1182
1183 current.left = new Node< K, V >( current, key, value );
1184 } else if ( current == current.parent.left && current.parent.right == null ) {
1185
1186
1187
1188 current.left = new Node< K, V >( current, key, value );
1189 current.parent.rotateRight( this );
1190 } else if ( current == current.parent.right && current.parent.left == null ) {
1191
1192
1193
1194 current.parent.insertPushLeft( this, key, value );
1195 } else {
1196
1197 current.left = new Node< K, V >( current, key, value );
1198 }
1199 break;
1200 } else {
1201 current = current.left;
1202 }
1203 } else {
1204
1205 if ( current.right == null ) {
1206
1207
1208 if ( current.parent == null ) {
1209
1210
1211
1212 current.right = new Node< K, V >( current, key, value );
1213 } else if ( current == current.parent.right && current.parent.left == null ) {
1214
1215
1216
1217 current.right = new Node< K, V >( current, key, value );
1218 current.parent.rotateLeft( this );
1219 } else if ( current == current.parent.left && current.parent.right == null ) {
1220
1221
1222
1223 current.parent.insertPushRight( this, key, value );
1224 } else {
1225
1226 current.right = new Node< K, V >( current, key, value );
1227 }
1228 break;
1229 } else {
1230 current = current.right;
1231 }
1232 }
1233 }
1234
1235 while ( current != null ) {
1236 current.updateSize();
1237 current = current.parent;
1238 }
1239 }
1240 }
1241
1242 /**
1243 * @see org.millscript.commons.util.IMap#iterator(boolean)
1244 */
1245 public MapIterator< K, V > iterator( final boolean share ) {
1246 return new NodeIterator< K, V >( this.root, share );
1247 }
1248
1249 /**
1250 * Reads this object from the specified {@link ObjectInputStream}.
1251 *
1252 * @param stream the {@link ObjectInputStream} to read the objects data
1253 * from
1254 * @serialData Reads the default object, followed by the integer
1255 * number of mappings and then an alternating sequence of key-value pairs
1256 * @throws ClassNotFoundException if a required class cannot be found
1257 * @throws IOException if something goes wrong during the
1258 * deserialization process
1259 */
1260 @SuppressWarnings( "unchecked" )
1261 private void readObject( final ObjectInputStream stream ) throws ClassNotFoundException, IOException {
1262
1263 stream.defaultReadObject();
1264
1265 final int size = stream.readInt();
1266
1267 final K[] keys = (K[]) new Comparable[ size ];
1268 final V[] values = (V[]) new Comparable[ size ];
1269 for ( int i = 0; i < size; i++ ) {
1270 keys[ i ] = (K) stream.readObject();
1271 values[ i ] = (V) stream.readObject();
1272 }
1273 this.root = new Node< K, V >( null, keys, values, 1, size );
1274 }
1275
1276 /**
1277 * @see org.millscript.commons.util.EMap#remove(java.lang.Object, java.lang.Object)
1278 */
1279 public void remove( final K key, final V value ) {
1280 if ( this.root != null ) {
1281 Node< K, V > current = this.root;
1282 Node< K, V > parent = null;
1283 while ( current != null ) {
1284 final int comp = this.compare( key, current.key );
1285 if ( comp == 0 ) {
1286
1287
1288 if ( value == null ? current.value == null : value.equals( current.value ) ) {
1289
1290 current = current.remove( this );
1291 break;
1292 }
1293 } else if ( comp < 0 ) {
1294
1295 parent = current;
1296 current = current.left;
1297 } else {
1298
1299 parent = current;
1300 current = current.right;
1301 }
1302 }
1303
1304 while ( parent != null ) {
1305 parent.updateSize();
1306 parent = parent.parent;
1307 }
1308 }
1309 }
1310
1311 /**
1312 * @see org.millscript.commons.util.EMap#removeAll()
1313 */
1314 public void removeAll() {
1315 this.root = null;
1316 }
1317
1318 /**
1319 * @see org.millscript.commons.util.EMap#removeKey(java.lang.Object)
1320 */
1321 public void removeKey( final K key ) {
1322 if ( this.root != null ) {
1323 Node< K, V > current = this.root;
1324 while ( current != null ) {
1325 final int comp = this.compare( key, current.key );
1326 if ( comp == 0 ) {
1327
1328 current = current.remove( this );
1329 break;
1330 } else if ( comp < 0 ) {
1331
1332 current = current.left;
1333 } else {
1334
1335 current = current.right;
1336 }
1337 }
1338
1339 while ( current != null ) {
1340 current.updateSize();
1341 current = current.parent;
1342 }
1343 }
1344 }
1345
1346 /**
1347 * @see org.millscript.commons.util.EMap#removeValue(java.lang.Object)
1348 */
1349 public void removeValue( final V value ) {
1350 if ( this.root != null ) {
1351 Node< K, V > current = this.root.getLeftmost();
1352 while ( current != null ) {
1353 if ( value == null ? current.value == null : value.equals( current.value ) ) {
1354 current = current.remove( this );
1355 for ( Node fixsize = current; fixsize != null; fixsize = fixsize.parent ) {
1356 fixsize.updateSize();
1357 }
1358 } else {
1359 current = current.getNextInSequence();
1360 }
1361 }
1362 }
1363 }
1364
1365 /**
1366 * @see org.millscript.commons.util.map.AbstractIMap#sharedKeyList()
1367 */
1368 @Override
1369 protected IList< K > sharedKeyList() {
1370 return new NodeKeyList< K >( this.root, 1, this.size() );
1371 }
1372
1373 /**
1374 * @see org.millscript.commons.util.map.AbstractIMap#sharedMapletList()
1375 */
1376 @Override
1377 protected IList< Maplet< K, V > > sharedMapletList() {
1378 return new NodeMapletList< K, V >( this.root, 1, this.size() );
1379 }
1380
1381 /**
1382 * @see org.millscript.commons.util.map.AbstractIMap#sharedValueList()
1383 */
1384 @Override
1385 protected IList< V > sharedValueList() {
1386 return new NodeValueList< V >( this.root, 1, this.size() );
1387 }
1388
1389 /**
1390 * @see org.millscript.commons.util.IMap#size()
1391 */
1392 public int size() {
1393 return this.root == null ? 0 : this.root.size;
1394 }
1395
1396 /**
1397 * @see org.millscript.commons.util.UMap#update(java.lang.Object, java.lang.Object)
1398 */
1399 public void update( final K key, final V value ) {
1400 if ( this.root != null ) {
1401 Node< K, V > current = this.root;
1402 while ( current != null ) {
1403 final int comp = this.compare( key, current.key );
1404 if ( comp == 0 ) {
1405
1406 current.value = value;
1407 return;
1408 } else if ( comp < 0 ) {
1409
1410 current = current.left;
1411 } else {
1412
1413 current = current.right;
1414 }
1415 }
1416 }
1417 throw new NoSuchKeyInMapAlert(
1418 "Only pre-existing keys can have their values updated"
1419 ).culpritKey( key ).decorate( this ).mishap();
1420 }
1421
1422 /**
1423 * Writes this object to the specified {@link ObjectOutputStream}.
1424 *
1425 * @param stream the {@link ObjectOutputStream} to write this object to
1426 * @serialData Writes the default object and then an alternating
1427 * sequence of key-value pairs
1428 * @throws IOException if something goes wrong during the
1429 * serialization process
1430 */
1431 private void writeObject( final ObjectOutputStream stream ) throws IOException {
1432
1433 stream.defaultWriteObject();
1434