0001 /*
0002 * RBTreeMap.java
0003 *
0004 * Copyright (c) 1995-2010, The University of Sheffield. See the file
0005 * COPYRIGHT.txt in the software or at http://gate.ac.uk/gate/COPYRIGHT.txt
0006 *
0007 * This file is part of GATE (see http://gate.ac.uk/), and is free
0008 * software, licenced under the GNU Library General Public License,
0009 * Version 2, June 1991 (in the distribution as file licence.html,
0010 * and also available at http://gate.ac.uk/gate/licence.html).
0011 *
0012 * Valentin Tablan, Jan/2000, modified from Sun sources
0013 *
0014 * $Id: RBTreeMap.java 12006 2009-12-01 17:24:28Z thomas_heitz $
0015 */
0016
0017 package gate.util;
0018 import java.util.*;
0019
0020 /** Slightly modified implementation of java.util.TreeMap in order to return the
0021 * closest neighbours in the case of a failed search.
0022 */
0023 public class RBTreeMap extends AbstractMap
0024 implements SortedMap, Cloneable, java.io.Serializable
0025 {
0026 /** Debug flag */
0027 private static final boolean DEBUG = false;
0028
0029 /** Freeze the serialization UID. */
0030 static final long serialVersionUID = -1454324265766936618L;
0031
0032 /**
0033 * The Comparator used to maintain order in this RBTreeMap, or
0034 * null if this RBTreeMap uses its elements natural ordering.
0035 *
0036 * @serial
0037 */
0038 private Comparator comparator = null;
0039
0040 private transient Entry root = null;
0041
0042 /**
0043 * The number of entries in the tree
0044 */
0045 private transient int size = 0;
0046
0047 /**
0048 * The number of structural modifications to the tree.
0049 */
0050 private transient int modCount = 0;
0051
0052 private void incrementSize() { modCount++; size++; }
0053 private void decrementSize() { modCount++; size--; }
0054
0055 /**
0056 * Constructs a new, empty map, sorted according to the keys' natural
0057 * order. All keys inserted into the map must implement the
0058 * <tt>Comparable</tt> interface. Furthermore, all such keys must be
0059 * <i>mutually comparable</i>: <tt>k1.compareTo(k2)</tt> must not throw a
0060 * ClassCastException for any elements <tt>k1</tt> and <tt>k2</tt> in the
0061 * map. If the user attempts to put a key into the map that violates this
0062 * constraint (for example, the user attempts to put a string key into a
0063 * map whose keys are integers), the <tt>put(Object key, Object
0064 * value)</tt> call will throw a <tt>ClassCastException</tt>.
0065 *
0066 * @see Comparable
0067 */
0068 public RBTreeMap() {
0069 }
0070
0071 /**
0072 * Constructs a new, empty map, sorted according to the given comparator.
0073 * All keys inserted into the map must be <i>mutually comparable</i> by
0074 * the given comparator: <tt>comparator.compare(k1, k2)</tt> must not
0075 * throw a <tt>ClassCastException</tt> for any keys <tt>k1</tt> and
0076 * <tt>k2</tt> in the map. If the user attempts to put a key into the
0077 * map that violates this constraint, the <tt>put(Object key, Object
0078 * value)</tt> call will throw a <tt>ClassCastException</tt>.
0079 */
0080 public RBTreeMap(Comparator c) {
0081 this.comparator = c;
0082 }
0083
0084 /**
0085 * Constructs a new map containing the same mappings as the given map,
0086 * sorted according to the keys' <i>natural order</i>. All keys inserted
0087 * into the new map must implement the <tt>Comparable</tt> interface.
0088 * Furthermore, all such keys must be <i>mutually comparable</i>:
0089 * <tt>k1.compareTo(k2)</tt> must not throw a <tt>ClassCastException</tt>
0090 * for any elements <tt>k1</tt> and <tt>k2</tt> in the map. This method
0091 * runs in n*log(n) time.
0092 *
0093 * @throws ClassCastException the keys in t are not Comparable, or
0094 * are not mutually comparable.
0095 */
0096 public RBTreeMap(Map m) {
0097 putAll(m);
0098 }
0099
0100 /**
0101 * Constructs a new map containing the same mappings as the given
0102 * <tt>SortedMap</tt>, sorted according to the same ordering. This method
0103 * runs in linear time.
0104 */
0105 public RBTreeMap(SortedMap m) {
0106 comparator = m.comparator();
0107 try {
0108 buildFromSorted(m.size(), m.entrySet().iterator(), null, null);
0109 } catch (java.io.IOException cannotHappen) {
0110 } catch (ClassNotFoundException cannotHappen) {
0111 }
0112 }
0113
0114
0115 // Query Operations
0116
0117 /**
0118 * Returns the number of key-value mappings in this map.
0119 *
0120 * @return the number of key-value mappings in this map.
0121 */
0122 public int size() {
0123 return size;
0124 }
0125
0126 /**
0127 * Returns <tt>true</tt> if this map contains a mapping for the specified
0128 * key.
0129 *
0130 * @param key key whose presence in this map is to be tested.
0131 *
0132 * @return <tt>true</tt> if this map contains a mapping for the
0133 * specified key.
0134 * @throws ClassCastException if the key cannot be compared with the keys
0135 * currently in the map.
0136 * @throws NullPointerException key is <tt>null</tt> and this map uses
0137 * natural ordering, or its comparator does not tolerate
0138 * <tt>null</tt> keys.
0139 */
0140 public boolean containsKey(Object key) {
0141 return getEntry(key) != null;
0142 }
0143
0144 /**
0145 * Returns <tt>true</tt> if this map maps one or more keys to the
0146 * specified value. More formally, returns <tt>true</tt> if and only if
0147 * this map contains at least one mapping to a value <tt>v</tt> such
0148 * that <tt>(value==null ? v==null : value.equals(v))</tt>. This
0149 * operation will probably require time linear in the Map size for most
0150 * implementations of Map.
0151 *
0152 * @param value value whose presence in this Map is to be tested.
0153 * @since JDK1.2
0154 */
0155 public boolean containsValue(Object value) {
0156 return (value==null ? valueSearchNull(root)
0157 : valueSearchNonNull(root, value));
0158 }
0159
0160 private boolean valueSearchNull(Entry n) {
0161 if (n.value == null)
0162 return true;
0163
0164 // Check left and right subtrees for value
0165 return (n.left != null && valueSearchNull(n.left)) ||
0166 (n.right != null && valueSearchNull(n.right));
0167 }
0168
0169 private boolean valueSearchNonNull(Entry n, Object value) {
0170 // Check this node for the value
0171 if (value.equals(n.value))
0172 return true;
0173
0174 // Check left and right subtrees for value
0175 return (n.left != null && valueSearchNonNull(n.left, value)) ||
0176 (n.right != null && valueSearchNonNull(n.right, value));
0177 }
0178
0179 /**
0180 * Returns a pair of values: (glb,lub).
0181 * If the given key is found in the map then glb=lub=the value associated
0182 * with the given key.
0183 * If the key is not in the map:
0184 * glb=the value associated with the greatest key in the map that is lower
0185 * than the given key; or null if the given key is smaller than any key in
0186 * the map.
0187 * lub=the value associated with the smaller key in the map that is greater
0188 * than the given key; or null the given key is greater than any key in the
0189 * map.
0190 * If the map is empty it returns (null,null).
0191 */
0192 public Object[] getClosestMatch(Object key){
0193 if (root==null)return new Object[]{null,null};
0194
0195 Entry lub=getCeilEntry(key);
0196
0197 if(lub==null){//greatest key in set is still smaller then parameter "key"
0198 return new Object[]{lastEntry().value,null};
0199 };
0200
0201 int cmp=compare(key,lub.key);
0202
0203 if (cmp==0){return new Object[]{lub.value,lub.value};}
0204 else {
0205 Entry prec=getPrecedingEntry(lub.key);
0206 if (prec == null) return new Object[]{null,lub.value};
0207 else return new Object[]{prec.value,lub.value};
0208 }
0209 }
0210
0211 /** Returns the value associated to the next key in the map if an exact match
0212 * doesn't exist. If there is an exact match, the method will return the
0213 * value associated to the given key.
0214 * @param key the key for wich the look-up will be done.
0215 * @return the value associated to the given key or the next available
0216 * value
0217 */
0218 public Object getNextOf(Object key){
0219 if (root==null) return null;
0220 Entry lub=getCeilEntry(key);
0221 if (lub == null) return null;
0222 return lub.value;
0223 }
0224
0225 /**
0226 * Returns the value to which this map maps the specified key. Returns
0227 * <tt>null</tt> if the map contains no mapping for this key. A return
0228 * value of <tt>null</tt> does not <i>necessarily</i> indicate that the
0229 * map contains no mapping for the key; it's also possible that the map
0230 * explicitly maps the key to <tt>null</tt>. The <tt>containsKey</tt>
0231 * operation may be used to distinguish these two cases.
0232 *
0233 * @param key key whose associated value is to be returned.
0234 * @return the value to which this map maps the specified key, or
0235 * <tt>null</tt> if the map contains no mapping for the key.
0236 * @throws ClassCastException key cannot be compared with the keys
0237 * currently in the map.
0238 * @throws NullPointerException key is <tt>null</tt> and this map uses
0239 * natural ordering, or its comparator does not tolerate
0240 * <tt>null</tt> keys.
0241 *
0242 * @see #containsKey(Object)
0243 */
0244 public Object get(Object key) {
0245 Entry p = getEntry(key);
0246 return (p==null ? null : p.value);
0247 }
0248
0249 /**
0250 * Returns the comparator used to order this map, or <tt>null</tt> if this
0251 * map uses its keys' natural order.
0252 *
0253 * @return the comparator associated with this sorted map, or
0254 * <tt>null</tt> if it uses its keys' natural sort method.
0255 */
0256 public Comparator comparator() {
0257 return comparator;
0258 }
0259
0260 /**
0261 * Returns the first (lowest) key currently in this sorted map.
0262 *
0263 * @return the first (lowest) key currently in this sorted map.
0264 * @throws NoSuchElementException Map is empty.
0265 */
0266 public Object firstKey() {
0267 return key(firstEntry());
0268 }
0269
0270 /**
0271 * Returns the last (highest) key currently in this sorted map.
0272 *
0273 * @return the last (highest) key currently in this sorted map.
0274 * @throws NoSuchElementException Map is empty.
0275 */
0276 public Object lastKey() {
0277 return key(lastEntry());
0278 }
0279
0280 /**
0281 * Copies all of the mappings from the specified map to this map. These
0282 * mappings replace any mappings that this map had for any of the keys
0283 * currently in the specified map.
0284 *
0285 * @param map Mappings to be stored in this map.
0286 * @throws ClassCastException class of a key or value in the specified
0287 * map prevents it from being stored in this map.
0288 *
0289 * @throws NullPointerException this map does not permit <tt>null</tt>
0290 * keys and a specified key is <tt>null</tt>.
0291 */
0292 public void putAll(Map map) {
0293 int mapSize = map.size();
0294 if (size==0 && mapSize!=0 && map instanceof SortedMap) {
0295 Comparator c = ((SortedMap)map).comparator();
0296 if (c == comparator || (c != null && c.equals(comparator))) {
0297 ++modCount;
0298 try {
0299 buildFromSorted(mapSize, map.entrySet().iterator(),
0300 null, null);
0301 } catch (java.io.IOException cannotHappen) {
0302 } catch (ClassNotFoundException cannotHappen) {
0303 }
0304 return;
0305 }
0306 }
0307 super.putAll(map);
0308 }
0309
0310 /**
0311 * Returns this map's entry for the given key, or <tt>null</tt> if the map
0312 * does not contain an entry for the key.
0313 *
0314 * @return this map's entry for the given key, or <tt>null</tt> if the map
0315 * does not contain an entry for the key.
0316 * @throws ClassCastException if the key cannot be compared with the keys
0317 * currently in the map.
0318 * @throws NullPointerException key is <tt>null</tt> and this map uses
0319 * natural order, or its comparator does not tolerate *
0320 * <tt>null</tt> keys.
0321 */
0322 private Entry getEntry(Object key) {
0323 Entry p = root;
0324 while (p != null) {
0325 int cmp = compare(key,p.key);
0326 if (cmp == 0)
0327 return p;
0328 else if (cmp < 0)
0329 p = p.left;
0330 else
0331 p = p.right;
0332 }
0333 return null;
0334 }
0335
0336
0337 /**
0338 * Gets the entry corresponding to the specified key; if no such entry
0339 * exists, returns the entry for the least key greater than the specified
0340 * key; if no such entry exists (i.e., the greatest key in the Tree is less
0341 * than the specified key), returns <tt>null</tt>.
0342 */
0343 private Entry getCeilEntry(Object key) {
0344 Entry p = root;
0345 if (p==null)
0346 return null;
0347
0348 while (true) {
0349 int cmp = compare(key, p.key);
0350 if (cmp == 0) {
0351 return p;
0352 } else if (cmp < 0) {
0353 if (p.left != null)
0354 p = p.left;
0355 else
0356 return p;
0357 } else {
0358 if (p.right != null) {
0359 p = p.right;
0360 } else {
0361 Entry parent = p.parent;
0362 Entry ch = p;
0363 while (parent != null && ch == parent.right) {
0364 ch = parent;
0365 parent = parent.parent;
0366 }
0367 return parent;
0368 }
0369 }
0370 }
0371 }
0372
0373 /**
0374 * Returns the entry for the greatest key less than the specified key; if
0375 * no such entry exists (i.e., the least key in the Tree is greater than
0376 * the specified key), returns <tt>null</tt>.
0377 */
0378 private Entry getPrecedingEntry(Object key) {
0379 Entry p = root;
0380 if (p==null)return null;
0381
0382 while (true) {
0383 int cmp = compare(key, p.key);
0384 if (cmp > 0) {
0385 if (p.right != null) p = p.right;
0386 else return p;
0387 }else{
0388 if (p.left != null) {
0389 p = p.left;
0390 } else {
0391 Entry parent = p.parent;
0392 Entry ch = p;
0393 while (parent != null && ch == parent.left) {
0394 ch = parent;
0395 parent = parent.parent;
0396 }
0397 return parent;
0398 }
0399 }
0400 }//while true
0401 }
0402
0403 /**
0404 * Returns the key corresonding to the specified Entry. Throw
0405 * NoSuchElementException if the Entry is <tt>null</tt>.
0406 */
0407 private static Object key(Entry e) {
0408 if (e==null)
0409 throw new NoSuchElementException();
0410 return e.key;
0411 }
0412
0413 /**
0414 * Associates the specified value with the specified key in this map.
0415 * If the map previously contained a mapping for this key, the old
0416 * value is replaced.
0417 *
0418 * @param key key with which the specified value is to be associated.
0419 * @param value value to be associated with the specified key.
0420 *
0421 * @return previous value associated with specified key, or <tt>null</tt>
0422 * if there was no mapping for key. A <tt>null</tt> return can
0423 * also indicate that the map previously associated <tt>null</tt>
0424 * with the specified key.
0425 * @throws ClassCastException key cannot be compared with the keys
0426 * currently in the map.
0427 * @throws NullPointerException key is <tt>null</tt> and this map uses
0428 * natural order, or its comparator does not tolerate
0429 * <tt>null</tt> keys.
0430 */
0431 public Object put(Object key, Object value) {
0432 Entry t = root;
0433
0434 if (t == null) {
0435 incrementSize();
0436 root = new Entry(key, value, null);
0437 return null;
0438 }
0439
0440 while (true) {
0441 int cmp = compare(key, t.key);
0442 if (cmp == 0) {
0443 return t.setValue(value);
0444 } else if (cmp < 0) {
0445 if (t.left != null) {
0446 t = t.left;
0447 } else {
0448 incrementSize();
0449 t.left = new Entry(key, value, t);
0450 fixAfterInsertion(t.left);
0451 return null;
0452 }
0453 } else { // cmp > 0
0454 if (t.right != null) {
0455 t = t.right;
0456 } else {
0457 incrementSize();
0458 t.right = new Entry(key, value, t);
0459 fixAfterInsertion(t.right);
0460 return null;
0461 }
0462 }
0463 }
0464 }
0465
0466 /**
0467 * Removes the mapping for this key from this RBTreeMap if present.
0468 *
0469 * @return previous value associated with specified key, or <tt>null</tt>
0470 * if there was no mapping for key. A <tt>null</tt> return can
0471 * also indicate that the map previously associated
0472 * <tt>null</tt> with the specified key.
0473 *
0474 * @throws ClassCastException key cannot be compared with the keys
0475 * currently in the map.
0476 * @throws NullPointerException key is <tt>null</tt> and this map uses
0477 * natural order, or its comparator does not tolerate
0478 * <tt>null</tt> keys.
0479 */
0480 public Object remove(Object key) {
0481 Entry p = getEntry(key);
0482 if (p == null)
0483 return null;
0484
0485 Object oldValue = p.value;
0486 deleteEntry(p);
0487 return oldValue;
0488 }
0489
0490 /**
0491 * Removes all mappings from this RBTreeMap.
0492 */
0493 public void clear() {
0494 modCount++;
0495 size = 0;
0496 root = null;
0497 }
0498
0499 /**
0500 * Returns a shallow copy of this <tt>RBTreeMap</tt> instance. (The keys and
0501 * values themselves are not cloned.)
0502 *
0503 * @return a shallow copy of this Map.
0504 */
0505 public Object clone() {
0506 return new RBTreeMap(this);
0507 }
0508
0509
0510 // Views
0511
0512 /**
0513 * These fields are initialized to contain an instance of the appropriate
0514 * view the first time this view is requested. The views are stateless,
0515 * so there's no reason to create more than one of each.
0516 */
0517 private transient Set keySet = null;
0518 private transient Set entrySet = null;
0519 private transient Collection values = null;
0520
0521 /**
0522 * Returns a Set view of the keys contained in this map. The set's
0523 * iterator will return the keys in ascending order. The map is backed by
0524 * this <tt>RBTreeMap</tt> instance, so changes to this map are reflected in
0525 * the Set, and vice-versa. The Set supports element removal, which
0526 * removes the corresponding mapping from the map, via the
0527 * <tt>Iterator.remove</tt>, <tt>Set.remove</tt>, <tt>removeAll</tt>,
0528 * <tt>retainAll</tt>, and <tt>clear</tt> operations. It does not support
0529 * the <tt>add</tt> or <tt>addAll</tt> operations.
0530 *
0531 * @return a set view of the keys contained in this RBTreeMap.
0532 */
0533 public Set keySet() {
0534 if (keySet == null) {
0535 keySet = new AbstractSet() {
0536
0537 public java.util.Iterator iterator() {
0538 return new Iterator(KEYS);
0539 }
0540
0541 public int size() {
0542 return RBTreeMap.this.size();
0543 }
0544
0545 public boolean contains(Object o) {
0546 return containsKey(o);
0547 }
0548
0549 public boolean remove(Object o) {
0550 return RBTreeMap.this.remove(o) != null;
0551 }
0552
0553 public void clear() {
0554 RBTreeMap.this.clear();
0555 }
0556 };
0557 }
0558 return keySet;
0559 }
0560
0561 /**
0562 * Returns a collection view of the values contained in this map. The
0563 * collection's iterator will return the values in the order that their
0564 * corresponding keys appear in the tree. The collection is backed by
0565 * this <tt>RBTreeMap</tt> instance, so changes to this map are reflected in
0566 * the collection, and vice-versa. The collection supports element
0567 * removal, which removes the corresponding mapping from the map through
0568 * the <tt>Iterator.remove</tt>, <tt>Collection.remove</tt>,
0569 * <tt>removeAll</tt>, <tt>retainAll</tt>, and <tt>clear</tt> operations.
0570 * It does not support the <tt>add</tt> or <tt>addAll</tt> operations.
0571 *
0572 * @return a collection view of the values contained in this map.
0573 */
0574 public Collection values() {
0575 if (values == null) {
0576 values = new AbstractCollection() {
0577 public java.util.Iterator iterator() {
0578 return new Iterator(VALUES);
0579 }
0580
0581 public int size() {
0582 return RBTreeMap.this.size();
0583 }
0584
0585 public boolean contains(Object o) {
0586 for (Entry e = firstEntry(); e != null; e = successor(e))
0587 if (valEquals(e.getValue(), o))
0588 return true;
0589 return false;
0590 }
0591
0592 public boolean remove(Object o) {
0593 for (Entry e = firstEntry(); e != null; e = successor(e)) {
0594 if (valEquals(e.getValue(), o)) {
0595 deleteEntry(e);
0596 return true;
0597 }
0598 }
0599 return false;
0600 }
0601
0602 public void clear() {
0603 RBTreeMap.this.clear();
0604 }
0605 };
0606 }
0607 return values;
0608 }
0609
0610 /**
0611 * Returns a set view of the mappings contained in this map. The set's
0612 * iterator returns the mappings in ascending key order. Each element in
0613 * the returned set is a <tt>Map.Entry</tt>. The set is backed by this
0614 * map, so changes to this map are reflected in the set, and vice-versa.
0615 * The set supports element removal, which removes the corresponding
0616 * mapping from the RBTreeMap, through the <tt>Iterator.remove</tt>,
0617 * <tt>Set.remove</tt>, <tt>removeAll</tt>, <tt>retainAll</tt> and
0618 * <tt>clear</tt> operations. It does not support the <tt>add</tt> or
0619 * <tt>addAll</tt> operations.
0620 *
0621 * @return a set view of the mappings contained in this map.
0622 * @see Map.Entry
0623 */
0624 public Set entrySet() {
0625 if (entrySet == null) {
0626 entrySet = new AbstractSet() {
0627 public java.util.Iterator iterator() {
0628 return new Iterator(ENTRIES);
0629 }
0630
0631 public boolean contains(Object o) {
0632 if (!(o instanceof Map.Entry))
0633 return false;
0634 Map.Entry entry = (Map.Entry)o;
0635 Object value = entry.getValue();
0636 Entry p = getEntry(entry.getKey());
0637 return p != null && valEquals(p.getValue(), value);
0638 }
0639
0640 public boolean remove(Object o) {
0641 if (!(o instanceof Map.Entry))
0642 return false;
0643 Map.Entry entry = (Map.Entry)o;
0644 Object value = entry.getValue();
0645 Entry p = getEntry(entry.getKey());
0646 if (p != null && valEquals(p.getValue(), value)) {
0647 deleteEntry(p);
0648 return true;
0649 }
0650 return false;
0651 }
0652
0653 public int size() {
0654 return RBTreeMap.this.size();
0655 }
0656
0657 public void clear() {
0658 RBTreeMap.this.clear();
0659 }
0660 };
0661 }
0662 return entrySet;
0663 }
0664
0665 /**
0666 * Returns a view of the portion of this map whose keys range from
0667 * <tt>fromKey</tt>, inclusive, to <tt>toKey</tt>, exclusive. (If
0668 * <tt>fromKey</tt> and <tt>toKey</tt> are equal, the returned sorted map
0669 * is empty.) The returned sorted map is backed by this map, so changes
0670 * in the returned sorted map are reflected in this map, and vice-versa.
0671 * The returned sorted map supports all optional map operations.<p>
0672 *
0673 * The sorted map returned by this method will throw an
0674 * <tt>IllegalArgumentException</tt> if the user attempts to insert a key
0675 * less than <tt>fromKey</tt> or greater than or equal to
0676 * <tt>toKey</tt>.<p>
0677 *
0678 * Note: this method always returns a <i>half-open range</i> (which
0679 * includes its low endpoint but not its high endpoint). If you need a
0680 * <i>closed range</i> (which includes both endpoints), and the key type
0681 * allows for calculation of the successor a given key, merely request the
0682 * subrange from <tt>lowEndpoint</tt> to <tt>successor(highEndpoint)</tt>.
0683 * For example, suppose that <tt>m</tt> is a sorted map whose keys are
0684 * strings. The following idiom obtains a view containing all of the
0685 * key-value mappings in <tt>m</tt> whose keys are between <tt>low</tt>
0686 * and <tt>high</tt>, inclusive:
0687 * <pre> SortedMap sub = m.submap(low, high+"\0");</pre>
0688 * A similar technique can be used to generate an <i>open range</i> (which
0689 * contains neither endpoint). The following idiom obtains a view
0690 * containing all of the key-value mappings in <tt>m</tt> whose keys are
0691 * between <tt>low</tt> and <tt>high</tt>, exclusive:
0692 * <pre> SortedMap sub = m.subMap(low+"\0", high);</pre>
0693 *
0694 * @param fromKey low endpoint (inclusive) of the subMap.
0695 * @param toKey high endpoint (exclusive) of the subMap.
0696 *
0697 * @return a view of the portion of this map whose keys range from
0698 * <tt>fromKey</tt>, inclusive, to <tt>toKey</tt>, exclusive.
0699 *
0700 * @throws NullPointerException if <tt>fromKey</tt> or <tt>toKey</tt> is
0701 * <tt>null</tt> and this map uses natural order, or its
0702 * comparator does not tolerate <tt>null</tt> keys.
0703 *
0704 * @throws IllegalArgumentException if <tt>fromKey</tt> is greater than
0705 * <tt>toKey</tt>.
0706 */
0707 public SortedMap subMap(Object fromKey, Object toKey) {
0708 return new SubMap(fromKey, toKey);
0709 }
0710
0711 /**
0712 * Returns a view of the portion of this map whose keys are strictly less
0713 * than <tt>toKey</tt>. The returned sorted map is backed by this map, so
0714 * changes in the returned sorted map are reflected in this map, and
0715 * vice-versa. The returned sorted map supports all optional map
0716 * operations.<p>
0717 *
0718 * The sorted map returned by this method will throw an
0719 * <tt>IllegalArgumentException</tt> if the user attempts to insert a key
0720 * greater than or equal to <tt>toKey</tt>.<p>
0721 *
0722 * Note: this method always returns a view that does not contain its
0723 * (high) endpoint. If you need a view that does contain this endpoint,
0724 * and the key type allows for calculation of the successor a given key,
0725 * merely request a headMap bounded by <tt>successor(highEndpoint)</tt>.
0726 * For example, suppose that suppose that <tt>m</tt> is a sorted map whose
0727 * keys are strings. The following idiom obtains a view containing all of
0728 * the key-value mappings in <tt>m</tt> whose keys are less than or equal
0729 * to <tt>high</tt>:
0730 * <pre>
0731 * SortedMap head = m.headMap(high+"\0");
0732 * </pre>
0733 *
0734 * @param toKey high endpoint (exclusive) of the headMap.
0735 * @return a view of the portion of this map whose keys are strictly
0736 * less than <tt>toKey</tt>.
0737 * @throws NullPointerException if <tt>toKey</tt> is <tt>null</tt> and
0738 * this map uses natural order, or its comparator does * not
0739 * tolerate <tt>null</tt> keys.
0740 */
0741 public SortedMap headMap(Object toKey) {
0742 return new SubMap(toKey, true);
0743 }
0744
0745 /**
0746 * Returns a view of the portion of this map whose keys are greater than
0747 * or equal to <tt>fromKey</tt>. The returned sorted map is backed by
0748 * this map, so changes in the returned sorted map are reflected in this
0749 * map, and vice-versa. The returned sorted map supports all optional map
0750 * operations.<p>
0751 *
0752 * The sorted map returned by this method will throw an
0753 * <tt>IllegalArgumentException</tt> if the user attempts to insert a key
0754 * less than <tt>fromKey</tt>.<p>
0755 *
0756 * Note: this method always returns a view that contains its (low)
0757 * endpoint. If you need a view that does not contain this endpoint, and
0758 * the element type allows for calculation of the successor a given value,
0759 * merely request a tailMap bounded by <tt>successor(lowEndpoint)</tt>.
0760 * For For example, suppose that suppose that <tt>m</tt> is a sorted map
0761 * whose keys are strings. The following idiom obtains a view containing
0762 * all of the key-value mappings in <tt>m</tt> whose keys are strictly
0763 * greater than <tt>low</tt>: <pre>
0764 * SortedMap tail = m.tailMap(low+"\0");
0765 * </pre>
0766 *
0767 * @param fromKey low endpoint (inclusive) of the tailMap.
0768 * @return a view of the portion of this map whose keys are greater
0769 * than or equal to <tt>fromKey</tt>.
0770 * @throws NullPointerException fromKey is <tt>null</tt> and this
0771 * map uses natural ordering, or its comparator does
0772 * not tolerate <tt>null</tt> keys.
0773 */
0774 public SortedMap tailMap(Object fromKey) {
0775 return new SubMap(fromKey, false);
0776 }
0777
0778 private class SubMap extends AbstractMap
0779 implements SortedMap, java.io.Serializable {
0780
0781 // fromKey is significant only if fromStart is false. Similarly,
0782 // toKey is significant only if toStart is false.
0783 private boolean fromStart = false, toEnd = false;
0784 private Object fromKey, toKey;
0785
0786 SubMap(Object fromKey, Object toKey) {
0787 if (compare(fromKey, toKey) > 0)
0788 throw new IllegalArgumentException("fromKey > toKey");
0789 this.fromKey = fromKey;
0790 this.toKey = toKey;
0791 }
0792
0793 SubMap(Object key, boolean headMap) {
0794 if (headMap) {
0795 fromStart = true;
0796 toKey = key;
0797 } else {
0798 toEnd = true;
0799 fromKey = key;
0800 }
0801 }
0802
0803 SubMap(boolean fromStart, Object fromKey, boolean toEnd, Object toKey){
0804 this.fromStart = fromStart;
0805 this.fromKey= fromKey;
0806 this.toEnd = toEnd;
0807 this.toKey = toKey;
0808 }
0809
0810 public boolean isEmpty() {
0811 return entrySet.isEmpty();
0812 }
0813
0814 public boolean containsKey(Object key) {
0815 return inRange(key) && RBTreeMap.this.containsKey(key);
0816 }
0817
0818 public Object get(Object key) {
0819 if (!inRange(key))
0820 return null;
0821 return RBTreeMap.this.get(key);
0822 }
0823
0824 public Object put(Object key, Object value) {
0825 if (!inRange(key))
0826 throw new IllegalArgumentException("key out of range");
0827 return RBTreeMap.this.put(key, value);
0828 }
0829
0830 public Comparator comparator() {
0831 return comparator;
0832 }
0833
0834 public Object firstKey() {
0835 return key(fromStart ? firstEntry() : getCeilEntry(fromKey));
0836 }
0837
0838 public Object lastKey() {
0839 return key(toEnd ? lastEntry() : getPrecedingEntry(toKey));
0840 }
0841
0842 private transient Set entrySet = new EntrySetView();
0843
0844 public Set entrySet() {
0845 return entrySet;
0846 }
0847
0848 private class EntrySetView extends AbstractSet {
0849 private transient int size = -1, sizeModCount;
0850
0851 public int size() {
0852 if (size == -1 || sizeModCount != RBTreeMap.this.modCount) {
0853 size = 0; sizeModCount = RBTreeMap.this.modCount;
0854 java.util.Iterator i = iterator();
0855 while (i.hasNext()) {
0856 size++;
0857 i.next();
0858 }
0859 }
0860 return size;
0861 } // size
0862
0863 public boolean isEmpty() {
0864 return !iterator().hasNext();
0865 }// isEmpty
0866
0867 public boolean contains(Object o) {
0868 if (!(o instanceof Map.Entry))
0869 return false;
0870
0871 Map.Entry entry = (Map.Entry)o;
0872 Object key = entry.getKey();
0873 if (!inRange(key))
0874 return false;
0875 RBTreeMap.Entry node = getEntry(key);
0876 return node != null &&
0877 valEquals(node.getValue(), entry.getValue());
0878 } // contains
0879
0880 public boolean remove(Object o) {
0881 if (!(o instanceof Map.Entry))
0882 return false;
0883 Map.Entry entry = (Map.Entry)o;
0884 Object key = entry.getKey();
0885 if (!inRange(key))
0886 return false;
0887 RBTreeMap.Entry node = getEntry(key);
0888 if (node!=null && valEquals(node.getValue(),entry.getValue())){
0889 deleteEntry(node);
0890 return true;
0891 }
0892 return false;
0893 }
0894
0895 public java.util.Iterator iterator() {
0896 return new Iterator(
0897 (fromStart ? firstEntry() : getCeilEntry(fromKey)),
0898 (toEnd ? null : getCeilEntry(toKey)));
0899 }
0900 } // EntrySetView
0901
0902 public SortedMap subMap(Object fromKey, Object toKey) {
0903 if (!inRange(fromKey))
0904 throw new IllegalArgumentException("fromKey out of range");
0905 if (!inRange2(toKey))
0906 throw new IllegalArgumentException("toKey out of range");
0907 return new SubMap(fromKey, toKey);
0908 }
0909
0910 public SortedMap headMap(Object toKey) {
0911 if (!inRange2(toKey))
0912 throw new IllegalArgumentException("toKey out of range");
0913 return new SubMap(fromStart, fromKey, false, toKey);
0914 }
0915
0916 public SortedMap tailMap(Object fromKey) {
0917 if (!inRange(fromKey))
0918 throw new IllegalArgumentException("fromKey out of range");
0919 return new SubMap(false, fromKey, toEnd, toKey);
0920 }
0921
0922 private boolean inRange(Object key) {
0923 return (fromStart || compare(key, fromKey) >= 0) &&
0924 (toEnd || compare(key, toKey) < 0);
0925 }
0926
0927 // This form allows the high endpoint (as well as all legit keys)
0928 private boolean inRange2(Object key) {
0929 return (fromStart || compare(key, fromKey) >= 0) &&
0930 (toEnd || compare(key, toKey) <= 0);
0931 }
0932 static final long serialVersionUID = 4333473260468321526L;
0933 } // SubMap
0934
0935 // Types of Iterators
0936 private static final int KEYS = 0;
0937
0938 private static final int VALUES = 1;
0939
0940 private static final int ENTRIES = 2;
0941
0942 /**
0943 * RBTreeMap Iterator.
0944 */
0945 private class Iterator implements java.util.Iterator {
0946 private int type;
0947
0948 private int expectedModCount = RBTreeMap.this.modCount;
0949
0950 private Entry lastReturned = null;
0951
0952 private Entry next;
0953
0954 private Entry firstExcluded = null;
0955
0956 Iterator(int type) {
0957 this.type = type;
0958 next = firstEntry();
0959 }
0960
0961 Iterator(Entry first, Entry firstExcluded) {
0962 type = ENTRIES;
0963 next = first;
0964 this.firstExcluded = firstExcluded;
0965 }
0966
0967 public boolean hasNext() {
0968 return next != firstExcluded;
0969 } //hasNext
0970
0971 public Object next() {
0972 if (next == firstExcluded)
0973 throw new NoSuchElementException();
0974
0975 if (modCount != expectedModCount)
0976 throw new ConcurrentModificationException();
0977
0978 lastReturned = next;
0979 next = successor(next);
0980 return (type == KEYS ? lastReturned.key :
0981 (type == VALUES ? lastReturned.value : lastReturned));
0982 } // next
0983
0984 public void remove() {
0985 if (lastReturned == null)
0986 throw new IllegalStateException();
0987
0988 if (modCount != expectedModCount)
0989 throw new ConcurrentModificationException();
0990
0991 deleteEntry(lastReturned);
0992 expectedModCount++;
0993 lastReturned = null;
0994 } // remove
0995 } //Iterator
0996
0997 /**
0998 * Compares two keys using the correct comparison method for this RBTreeMap.
0999 */
1000 private int compare(Object k1, Object k2) {
1001 return (comparator==null ? ((Comparable)k1).compareTo(k2)
1002 : comparator.compare(k1, k2));
1003 }
1004
1005 /**
1006 * Test two values for equality. Differs from o1.equals(o2) only in
1007 * that it copes with with <tt>null</tt> o1 properly.
1008 */
1009 private static boolean valEquals(Object o1, Object o2) {
1010 return (o1==null ? o2==null : o1.equals(o2));
1011 }
1012
1013 private static final boolean RED = false;
1014
1015 private static final boolean BLACK = true;
1016
1017 /**
1018 * Node in the Tree. Doubles as a means to pass key-value pairs back to
1019 * user (see Map.Entry).
1020 */
1021
1022 static class Entry implements Map.Entry {
1023 Object key;
1024 Object value;
1025 Entry left = null;
1026 Entry right = null;
1027 Entry parent;
1028 boolean color = BLACK;
1029
1030 /** Make a new cell with given key, value, and parent, and with
1031 * <tt>null</tt> child links, and BLACK color.
1032 */
1033 Entry(Object key, Object value, Entry parent) {
1034 this.key = key;
1035 this.value = value;
1036 this.parent = parent;
1037 }
1038
1039 /**
1040 * Returns the key.
1041 *
1042 * @return the key.
1043 */
1044 public Object getKey() {
1045 return key;
1046 }
1047
1048 /**
1049 * Returns the value associated with the key.
1050 *
1051 * @return the value associated with the key.
1052 */
1053 public Object getValue() {
1054 return value;
1055 }
1056
1057 /**
1058 * Replaces the value currently associated with the key with the given
1059 * value.
1060 *
1061 * @return the value associated with the key before this method was
1062 * called.
1063 */
1064 public Object setValue(Object value) {
1065 Object oldValue = this.value;
1066 this.value = value;
1067 return oldValue;
1068 }
1069
1070 public boolean equals(Object o) {
1071 if (!(o instanceof Map.Entry))
1072 return false;
1073 Map.Entry e = (Map.Entry)o;
1074
1075 return valEquals(key,e.getKey()) && valEquals(value,e.getValue());
1076 } // equals
1077
1078 public int hashCode() {
1079 int keyHash = (key==null ? 0 : key.hashCode());
1080 int valueHash = (value==null ? 0 : value.hashCode());
1081 return keyHash ^ valueHash;
1082 } // hashCode
1083
1084 public String toString() {
1085 return key + "=" + value;
1086 }
1087 } // Entry
1088
1089 /**
1090 * Returns the first Entry in the RBTreeMap (according to the RBTreeMap's
1091 * key-sort function). Returns null if the RBTreeMap is empty.
1092 */
1093 private Entry firstEntry() {
1094 Entry p = root;
1095 if (p != null)
1096 while (p.left != null)
1097 p = p.left;
1098 return p;
1099 }
1100
1101 /**
1102 * Returns the last Entry in the RBTreeMap (according to the RBTreeMap's
1103 * key-sort function). Returns null if the RBTreeMap is empty.
1104 */
1105 private Entry lastEntry() {
1106 Entry p = root;
1107 if (p != null)
1108 while (p.right != null)
1109 p = p.right;
1110 return p;
1111 }
1112
1113 /**
1114 * Returns the successor of the specified Entry, or null if no such.
1115 */
1116 private Entry successor(Entry t) {
1117 if (t == null)
1118 return null;
1119 else if (t.right != null) {
1120 Entry p = t.right;
1121 while (p.left != null)
1122 p = p.left;
1123 return p;
1124 } else {
1125 Entry p = t.parent;
1126 Entry ch = t;
1127 while (p != null && ch == p.right) {
1128 ch = p;
1129 p = p.parent;
1130 }
1131 return p;
1132 }
1133 } // successor
1134
1135 /**
1136 * Balancing operations.
1137 *
1138 * Implementations of rebalancings during insertion and deletion are
1139 * slightly different than the CLR version. Rather than using dummy
1140 * nilnodes, we use a set of accessors that deal properly with null. They
1141 * are used to avoid messiness surrounding nullness checks in the main
1142 * algorithms.
1143 */
1144
1145 private static boolean colorOf(Entry p) {
1146 return (p == null ? BLACK : p.color);
1147 }
1148
1149 private static Entry parentOf(Entry p) {
1150 return (p == null ? null: p.parent);
1151 }
1152
1153 private static void setColor(Entry p, boolean c) {
1154 if (p != null) p.color = c;
1155 }
1156
1157 private static Entry leftOf(Entry p) {
1158 return (p == null)? null: p.left;
1159 }
1160
1161 private static Entry rightOf(Entry p) {
1162 return (p == null)? null: p.right;
1163 }
1164
1165 /** From CLR **/
1166 private void rotateLeft(Entry p) {
1167 Entry r = p.right;
1168 p.right = r.left;
1169
1170 if (r.left != null)
1171 r.left.parent = p;
1172 r.parent = p.parent;
1173
1174 if (p.parent == null)
1175 root = r;
1176 else if (p.parent.left == p)
1177 p.parent.left = r;
1178 else
1179 p.parent.right = r;
1180 r.left = p;
1181 p.parent = r;
1182 }
1183
1184 /** From CLR **/
1185 private void rotateRight(Entry p) {
1186 Entry l = p.left;
1187 p.left = l.right;
1188
1189 if (l.right != null) l.right.parent = p;
1190 l.parent = p.parent;
1191
1192 if (p.parent == null)
1193 root = l;
1194 else if (p.parent.right == p)
1195 p.parent.right = l;
1196 else p.parent.left = l;
1197
1198 l.right = p;
1199 p.parent = l;
1200 }
1201
1202
1203 /** From CLR **/
1204 private void fixAfterInsertion(Entry x) {
1205 x.color = RED;
1206
1207 while (x != null && x != root && x.parent.color == RED) {
1208 if (parentOf(x) == leftOf(parentOf(parentOf(x)))) {
1209 Entry y = rightOf(parentOf(parentOf(x)));
1210 if (colorOf(y) == RED) {
1211 setColor(parentOf(x), BLACK);
1212 setColor(y, BLACK);
1213 setColor(parentOf(parentOf(x)), RED);
1214 x = parentOf(parentOf(x));
1215 } else {
1216 if (x == rightOf(parentOf(x))) {
1217 x = parentOf(x);
1218 rotateLeft(x);
1219 }
1220 setColor(parentOf(x), BLACK);
1221 setColor(parentOf(parentOf(x)), RED);
1222 if (parentOf(parentOf(x)) != null)
1223 rotateRight(parentOf(parentOf(x)));
1224 }
1225 } else {
1226 Entry y = leftOf(parentOf(parentOf(x)));
1227 if (colorOf(y) == RED) {
1228 setColor(parentOf(x), BLACK);
1229 setColor(y, BLACK);
1230 setColor(parentOf(parentOf(x)), RED);
1231 x = parentOf(parentOf(x));
1232 } else {
1233 if (x == leftOf(parentOf(x))) {
1234 x = parentOf(x);
1235 rotateRight(x);
1236 }
1237 setColor(parentOf(x), BLACK);
1238 setColor(parentOf(parentOf(x)), RED);
1239 if (parentOf(parentOf(x)) != null)
1240 rotateLeft(parentOf(parentOf(x)));
1241 }
1242 }
1243 }
1244 root.color = BLACK;
1245 } // fixAfterInsertion
1246
1247 /**
1248 * Delete node p, and then rebalance the tree.
1249 */
1250 private void deleteEntry(Entry p) {
1251 decrementSize();
1252
1253 // If strictly internal, first swap position with successor.
1254 if (p.left != null && p.right != null) {
1255 Entry s = successor(p);
1256 swapPosition(s, p);
1257 }
1258
1259 // Start fixup at replacement node, if it exists.
1260 Entry replacement = (p.left != null ? p.left : p.right);
1261
1262 if (replacement != null) {
1263 // Link replacement to parent
1264 replacement.parent = p.parent;
1265 if (p.parent == null)
1266 root = replacement;
1267 else if (p == p.parent.left)
1268 p.parent.left = replacement;
1269 else
1270 p.parent.right = replacement;
1271
1272 // Null out links so they are OK to use by fixAfterDeletion.
1273 p.left = p.right = p.parent = null;
1274
1275 // Fix replacement
1276 if (p.color == BLACK)
1277 fixAfterDeletion(replacement);
1278 } else if (p.parent == null) { // return if we are the only node.
1279 root = null;
1280 } else { // No children. Use self as phantom replacement and unlink.
1281 if (p.color == BLACK)
1282 fixAfterDeletion(p);
1283
1284 if (p.parent != null) {
1285 if (p == p.parent.left)
1286 p.parent.left = null;
1287 else if (p == p.parent.right)
1288 p.parent.right = null;
1289 p.parent = null;
1290 }
1291 }
1292 } // deleteEntry
1293
1294 /** From CLR **/
1295 private void fixAfterDeletion(Entry x) {
1296 while (x != root && colorOf(x) == BLACK) {
1297 if (x == leftOf(parentOf(x))) {
1298 Entry sib = rightOf(parentOf(x));
1299
1300 if (colorOf(sib) == RED) {
1301 setColor(sib, BLACK);
1302 setColor(parentOf(x), RED);
1303 rotateLeft(parentOf(x));
1304 sib = rightOf(parentOf(x));
1305 }
1306
1307 if (colorOf(leftOf(sib)) == BLACK &&
1308 colorOf(rightOf(sib)) == BLACK) {
1309 setColor(sib, RED);
1310 x = parentOf(x);
1311 } else {
1312 if (colorOf(rightOf(sib)) == BLACK) {
1313 setColor(leftOf(sib), BLACK);
1314 setColor(sib, RED);
1315 rotateRight(sib);
1316 sib = rightOf(parentOf(x));
1317 }
1318 setColor(sib, colorOf(parentOf(x)));
1319 setColor(parentOf(x), BLACK);
1320 setColor(rightOf(sib), BLACK);
1321 rotateLeft(parentOf(x));
1322 x = root;
1323 }
1324 } else { // symmetric
1325 Entry sib = leftOf(parentOf(x));
1326
1327 if (colorOf(sib) == RED) {
1328 setColor(sib, BLACK);
1329 setColor(parentOf(x), RED);
1330 rotateRight(parentOf(x));
1331 sib = leftOf(parentOf(x));
1332 }
1333
1334 if (colorOf(rightOf(sib)) == BLACK &&
1335 colorOf(leftOf(sib)) == BLACK) {
1336 setColor(sib, RED);
1337 x = parentOf(x);
1338 } else {
1339 if (colorOf(leftOf(sib)) == BLACK) {
1340 setColor(rightOf(sib), BLACK);
1341 setColor(sib, RED);
1342 rotateLeft(sib);
1343 sib = leftOf(parentOf(x));
1344 }
1345 setColor(sib, colorOf(parentOf(x)));
1346 setColor(parentOf(x), BLACK);
1347 setColor(leftOf(sib), BLACK);
1348 rotateRight(parentOf(x));
1349 x = root;
1350 }
1351 }
1352 }
1353 setColor(x, BLACK);
1354 } // fixAfterDeletion
1355
1356 /**
1357 * Swap the linkages of two nodes in a tree.
1358 */
1359 private void swapPosition(Entry x, Entry y) {
1360 // Save initial values.
1361 Entry px = x.parent, lx = x.left, rx = x.right;
1362 Entry py = y.parent, ly = y.left, ry = y.right;
1363 boolean xWasLeftChild = px != null && x == px.left;
1364 boolean yWasLeftChild = py != null && y == py.left;
1365
1366 // Swap, handling special cases of one being the other's parent.
1367 if (x == py) { // x was y's parent
1368 x.parent = y;
1369
1370 if (yWasLeftChild) {
1371 y.left = x;
1372 y.right = rx;
1373 } else {
1374 y.right = x;
1375 y.left = lx;
1376 }
1377 } else {
1378 x.parent = py;
1379
1380 if (py != null) {
1381 if (yWasLeftChild)
1382 py.left = x;
1383 else
1384 py.right = x;
1385 }
1386 y.left = lx;
1387 y.right = rx;
1388 }
1389
1390 if (y == px) { // y was x's parent
1391 y.parent = x;
1392 if (xWasLeftChild) {
1393 x.left = y;
1394 x.right = ry;
1395 } else {
1396 x.right = y;
1397 x.left = ly;
1398 }
1399 } else {
1400 y.parent = px;
1401 if (px != null) {
1402 if (xWasLeftChild)
1403 px.left = y;
1404 else
1405 px.right = y;
1406 }
1407 x.left = ly;
1408 x.right = ry;
1409 }
1410
1411 // Fix children's parent pointers
1412 if (x.left != null)
1413 x.left.parent = x;
1414
1415 if (x.right != null)
1416 x.right.parent = x;
1417
1418 if (y.left != null)
1419 y.left.parent = y;
1420
1421 if (y.right != null)
1422 y.right.parent = y;
1423
1424 // Swap colors
1425 boolean c = x.color;
1426 x.color = y.color;
1427 y.color = c;
1428
1429 // Check if root changed
1430 if (root == x)
1431 root = y;
1432 else if (root == y)
1433 root = x;
1434 } // swapPosition
1435
1436
1437
1438
1439 /**
1440 * Save the state of the <tt>RBTreeMap</tt> instance to a stream (i.e.,
1441 * serialize it).
1442 *
1443 * @serialData The <i>size</i> of the RBTreeMap (the number of key-value
1444 * mappings) is emitted (int), followed by the key (Object)
1445 * and value (Object) for each key-value mapping represented
1446 * by the RBTreeMap. The key-value mappings are emitted in
1447 * key-order (as determined by the RBTreeMap's Comparator,
1448 * or by the keys' natural ordering if the RBTreeMap has no
1449 * Comparator).
1450 */
1451 private void writeObject(java.io.ObjectOutputStream s)
1452 throws java.io.IOException {
1453
1454 // Write out the Comparator and any hidden stuff
1455 s.defaultWriteObject();
1456
1457 // Write out size (number of Mappings)
1458 s.writeInt(size);
1459
1460 // Write out keys and values (alternating)
1461 for (java.util.Iterator i = entrySet().iterator(); i.hasNext(); ) {
1462 Entry e = (Entry)i.next();
1463 s.writeObject(e.key);
1464 s.writeObject(e.value);
1465 }
1466 } // writeObject
1467
1468
1469
1470 /**
1471 * Reconstitute the <tt>RBTreeMap</tt> instance from a stream (i.e.,
1472 * deserialize it).
1473 */
1474 private void readObject(final java.io.ObjectInputStream s)
1475 throws java.io.IOException, ClassNotFoundException {
1476
1477 // Read in the Comparator and any hidden stuff
1478 s.defaultReadObject();
1479
1480 // Read in size
1481 int size = s.readInt();
1482
1483 buildFromSorted(size, null, s, null);
1484 } // readObject
1485
1486 /** Intended to be called only from TreeSet.readObject */
1487 void readTreeSet(int size, java.io.ObjectInputStream s, Object defaultVal)
1488 throws java.io.IOException, ClassNotFoundException {
1489 buildFromSorted(size, null, s, defaultVal);
1490 }
1491
1492 /** Intended to be called only from TreeSet.addAll */
1493 void addAllForTreeSet(SortedSet set, Object defaultVal) {
1494 try {
1495 buildFromSorted(set.size(), set.iterator(), null, defaultVal);
1496 } catch (java.io.IOException cannotHappen) {
1497 } catch (ClassNotFoundException cannotHappen) {
1498 }
1499 }
1500
1501
1502 /**
1503 * Linear time tree building algorithm from sorted data. Can accept keys
1504 * and/or values from iterator or stream. This leads to too many
1505 * parameters, but seems better than alternatives. The four formats
1506 * that this method accepts are:
1507 *
1508 * 1) An iterator of Map.Entries. (it != null, defaultVal == null).
1509 * 2) An iterator of keys. (it != null, defaultVal != null).
1510 * 3) A stream of alternating serialized keys and values.
1511 * (it == null, defaultVal == null).
1512 * 4) A stream of serialized keys. (it == null, defaultVal != null).
1513 *
1514 * It is assumed that the comparator of the RBTreeMap is already set prior
1515 * to calling this method.
1516 *
1517 * @param size the number of keys (or key-value pairs) to be read from
1518 * the iterator or stream.
1519 * @param it If non-null, new entries are created from entries
1520 * or keys read from this iterator.
1521 * @param str If non-null, new entries are created from keys and
1522 * possibly values read from this stream in serialized form.
1523 * Exactly one of it and str should be non-null.
1524 * @param defaultVal if non-null, this default value is used for
1525 * each value in the map. If null, each value is read from
1526 * iterator or stream, as described above.
1527 * @throws IOException propagated from stream reads. This cannot
1528 * occur if str is null.
1529 * @throws ClassNotFoundException propagated from readObject.
1530 * This cannot occur if str is null.
1531 */
1532 private void buildFromSorted(int size, java.util.Iterator it,
1533 java.io.ObjectInputStream str,
1534 Object defaultVal)
1535 throws java.io.IOException, ClassNotFoundException {
1536
1537 this.size = size;
1538 root = buildFromSorted(0, 0, size-1, computeRedLevel(size),
1539 it, str, defaultVal);
1540 } // buildFromSorted
1541
1542 /**
1543 * Recursive "helper method" that does the real work of the
1544 * of the previous method. Identically named parameters have
1545 * identical definitions. Additional parameters are documented below.
1546 * It is assumed that the comparator and size fields of the RBTreeMap are
1547 * already set prior to calling this method. (It ignores both fields.)
1548 *
1549 * @param level the current level of tree. Initial call should be 0.
1550 * @param lo the first element index of this subtree. Initial should be 0.
1551 * @param hi the last element index of this subtree. Initial should be
1552 * size-1.
1553 * @param redLevel the level at which nodes should be red.
1554 * Must be equal to computeRedLevel for tree of this size.
1555 */
1556 private static Entry buildFromSorted(int level, int lo, int hi,
1557 int redLevel,
1558 java.util.Iterator it,
1559 java.io.ObjectInputStream str,
1560 Object defaultVal)
1561 throws java.io.IOException, ClassNotFoundException {
1562 /*
1563 * Strategy: The root is the middlemost element. To get to it, we
1564 * have to first recursively construct the entire left subtree,
1565 * so as to grab all of its elements. We can then proceed with right
1566 * subtree.
1567 *
1568 * The lo and hi arguments are the minimum and maximum
1569 * indices to pull out of the iterator or stream for current subtree.
1570 * They are not actually indexed, we just proceed sequentially,
1571 * ensuring that items are extracted in corresponding order.
1572 */
1573
1574 if (hi < lo) return null;
1575
1576 int mid = (lo + hi) / 2;
1577
1578 Entry left = null;
1579 if (lo < mid)
1580 left = buildFromSorted(level+1, lo, mid - 1, redLevel,
1581 it, str, defaultVal);
1582
1583 // extract key and/or value from iterator or stream
1584 Object key;
1585 Object value;
1586
1587 if (it != null) { // use iterator
1588
1589 if (defaultVal==null) {
1590 Map.Entry entry = (Map.Entry) it.next();
1591 key = entry.getKey();
1592 value = entry.getValue();
1593 } else {
1594 key = it.next();
1595 value = defaultVal;
1596 }
1597 } else { // use stream
1598 key = str.readObject();
1599 value = (defaultVal != null ? defaultVal : str.readObject());
1600 }
1601
1602 Entry middle = new Entry(key, value, null);
1603
1604 // color nodes in non-full bottommost level red
1605 if (level == redLevel)
1606 middle.color = RED;
1607
1608 if (left != null) {
1609 middle.left = left;
1610 left.parent = middle;
1611 }
1612
1613 if (mid < hi) {
1614 Entry right = buildFromSorted(level+1, mid+1, hi, redLevel,
1615 it, str, defaultVal);
1616 middle.right = right;
1617 right.parent = middle;
1618 }
1619
1620 return middle;
1621
1622 } // Entry buildFromSorted
1623
1624 /**
1625 * Find the level down to which to assign all nodes BLACK. This is the
1626 * last `full' level of the complete binary tree produced by
1627 * buildTree. The remaining nodes are colored RED. (This makes a `nice'
1628 * set of color assignments wrt future insertions.) This level number is
1629 * computed by finding the number of splits needed to reach the zeroeth
1630 * node. (The answer is ~lg(N), but in any case must be computed by same
1631 * quick O(lg(N)) loop.)
1632 */
1633 private static int computeRedLevel(int sz) {
1634 int level = 0;
1635 for (int m = sz - 1; m >= 0; m = m / 2 - 1)
1636 level++;
1637 return level;
1638 }
1639
1640 } // class RBTreeMap
|