--- jsr166/src/main/java/util/TreeMap.java 2006/04/22 16:38:01 1.32
+++ jsr166/src/main/java/util/TreeMap.java 2010/09/01 07:48:47 1.49
@@ -1,8 +1,26 @@
/*
- * %W% %E%
+ * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
- * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
*/
package java.util;
@@ -68,14 +86,13 @@ package java.util;
* associated map using put.)
*
*
This class is a member of the
- *
+ *
* Java Collections Framework.
*
* @param the type of keys maintained by this map
* @param the type of mapped values
*
* @author Josh Bloch and Doug Lea
- * @version %I%, %G%
* @see Map
* @see HashMap
* @see Hashtable
@@ -109,9 +126,6 @@ public class TreeMap
*/
private transient int modCount = 0;
- private void incrementSize() { modCount++; size++; }
- private void decrementSize() { modCount++; size--; }
-
/**
* Constructs a new, empty tree map, using the natural ordering of its
* keys. All keys inserted into the map must implement the {@link
@@ -222,32 +236,14 @@ public class TreeMap
*
* @param value value whose presence in this map is to be tested
* @return true if a mapping to value exists;
- * false otherwise
+ * false otherwise
* @since 1.2
*/
public boolean containsValue(Object value) {
- return (root==null ? false :
- (value==null ? valueSearchNull(root)
- : valueSearchNonNull(root, value)));
- }
-
- private boolean valueSearchNull(Entry n) {
- if (n.value == null)
- return true;
-
- // Check left and right subtrees for value
- return (n.left != null && valueSearchNull(n.left)) ||
- (n.right != null && valueSearchNull(n.right));
- }
-
- private boolean valueSearchNonNull(Entry n, Object value) {
- // Check this node for the value
- if (value.equals(n.value))
- return true;
-
- // Check left and right subtrees for value
- return (n.left != null && valueSearchNonNull(n.left, value)) ||
- (n.right != null && valueSearchNonNull(n.right, value));
+ for (Entry e = getFirstEntry(); e != null; e = successor(e))
+ if (valEquals(value, e.value))
+ return true;
+ return false;
}
/**
@@ -312,14 +308,14 @@ public class TreeMap
if (size==0 && mapSize!=0 && map instanceof SortedMap) {
Comparator c = ((SortedMap)map).comparator();
if (c == comparator || (c != null && c.equals(comparator))) {
- ++modCount;
- try {
- buildFromSorted(mapSize, map.entrySet().iterator(),
- null, null);
- } catch (java.io.IOException cannotHappen) {
- } catch (ClassNotFoundException cannotHappen) {
- }
- return;
+ ++modCount;
+ try {
+ buildFromSorted(mapSize, map.entrySet().iterator(),
+ null, null);
+ } catch (java.io.IOException cannotHappen) {
+ } catch (ClassNotFoundException cannotHappen) {
+ }
+ return;
}
}
super.putAll(map);
@@ -343,7 +339,7 @@ public class TreeMap
return getEntryUsingComparator(key);
if (key == null)
throw new NullPointerException();
- Comparable super K> k = (Comparable super K>) key;
+ Comparable super K> k = (Comparable super K>) key;
Entry p = root;
while (p != null) {
int cmp = k.compareTo(p.key);
@@ -361,20 +357,22 @@ public class TreeMap
* Version of getEntry using comparator. Split off from getEntry
* for performance. (This is not worth doing for most methods,
* that are less dependent on comparator performance, but is
- * worthwhile for get and put.)
+ * worthwhile here.)
*/
final Entry getEntryUsingComparator(Object key) {
- K k = (K) key;
+ K k = (K) key;
Comparator super K> cpr = comparator;
- Entry p = root;
- while (p != null) {
- int cmp = cpr.compare(k, p.key);
- if (cmp < 0)
- p = p.left;
- else if (cmp > 0)
- p = p.right;
- else
- return p;
+ if (cpr != null) {
+ Entry p = root;
+ while (p != null) {
+ int cmp = cpr.compare(k, p.key);
+ if (cmp < 0)
+ p = p.left;
+ else if (cmp > 0)
+ p = p.right;
+ else
+ return p;
+ }
}
return null;
}
@@ -509,16 +507,6 @@ public class TreeMap
}
/**
- * Returns the key corresponding to the specified Entry.
- * @throws NoSuchElementException if the Entry is null
- */
- static K key(Entry e) {
- if (e==null)
- throw new NoSuchElementException();
- return e.key;
- }
-
- /**
* Associates the specified value with the specified key in this map.
* If the map previously contained a mapping for the key, the old
* value is replaced.
@@ -537,73 +525,57 @@ public class TreeMap
* does not permit null keys
*/
public V put(K key, V value) {
- // Offload comparator-based version for sake of performance
- if (comparator != null)
- return putUsingComparator(key, value);
- if (key == null)
- throw new NullPointerException();
- Comparable super K> k = (Comparable super K>) key;
-
Entry t = root;
- while (t != null) {
- int cmp = k.compareTo(t.key);
- if (cmp == 0) {
- return t.setValue(value);
- } else if (cmp < 0) {
- if (t.left != null) {
+ if (t == null) {
+ // TBD:
+ // 5045147: (coll) Adding null to an empty TreeSet should
+ // throw NullPointerException
+ //
+ // compare(key, key); // type check
+ root = new Entry(key, value, null);
+ size = 1;
+ modCount++;
+ return null;
+ }
+ int cmp;
+ Entry parent;
+ // split comparator and comparable paths
+ Comparator super K> cpr = comparator;
+ if (cpr != null) {
+ do {
+ parent = t;
+ cmp = cpr.compare(key, t.key);
+ if (cmp < 0)
t = t.left;
- } else {
- incrementSize();
- fixAfterInsertion(t.left = new Entry(key, value, t));
- return null;
- }
- } else { // cmp > 0
- if (t.right != null) {
+ else if (cmp > 0)
t = t.right;
- } else {
- incrementSize();
- fixAfterInsertion(t.right = new Entry(key, value, t));
- return null;
- }
- }
+ else
+ return t.setValue(value);
+ } while (t != null);
}
- incrementSize();
- root = new Entry(key, value, null);
- return null;
- }
-
- /**
- * Version of put using comparator. Split off from put for
- * performance.
- */
- final V putUsingComparator(K key, V value) {
- Comparator super K> cpr = comparator;
- Entry t = root;
- while (t != null) {
- int cmp = cpr.compare(key, t.key);
- if (cmp == 0) {
- return t.setValue(value);
- } else if (cmp < 0) {
- if (t.left != null) {
+ else {
+ if (key == null)
+ throw new NullPointerException();
+ Comparable super K> k = (Comparable super K>) key;
+ do {
+ parent = t;
+ cmp = k.compareTo(t.key);
+ if (cmp < 0)
t = t.left;
- } else {
- incrementSize();
- fixAfterInsertion(t.left = new Entry(key, value, t));
- return null;
- }
- } else { // cmp > 0
- if (t.right != null) {
+ else if (cmp > 0)
t = t.right;
- } else {
- incrementSize();
- fixAfterInsertion(t.right = new Entry(key, value, t));
- return null;
- }
- }
+ else
+ return t.setValue(value);
+ } while (t != null);
}
- cpr.compare(key, key); // type check
- incrementSize();
- root = new Entry(key, value, null);
+ Entry e = new Entry(key, value, parent);
+ if (cmp < 0)
+ parent.left = e;
+ else
+ parent.right = e;
+ fixAfterInsertion(e);
+ size++;
+ modCount++;
return null;
}
@@ -679,16 +651,14 @@ public class TreeMap
* @since 1.6
*/
public Map.Entry firstEntry() {
- Entry e = getFirstEntry();
- return (e == null)? null : new AbstractMap.SimpleImmutableEntry(e);
+ return exportEntry(getFirstEntry());
}
/**
* @since 1.6
*/
public Map.Entry lastEntry() {
- Entry e = getLastEntry();
- return (e == null)? null : new AbstractMap.SimpleImmutableEntry(e);
+ return exportEntry(getLastEntry());
}
/**
@@ -696,10 +666,9 @@ public class TreeMap
*/
public Map.Entry pollFirstEntry() {
Entry p = getFirstEntry();
- if (p == null)
- return null;
- Map.Entry result = new AbstractMap.SimpleImmutableEntry(p);
- deleteEntry(p);
+ Map.Entry result = exportEntry(p);
+ if (p != null)
+ deleteEntry(p);
return result;
}
@@ -708,10 +677,9 @@ public class TreeMap
*/
public Map.Entry pollLastEntry() {
Entry p = getLastEntry();
- if (p == null)
- return null;
- Map.Entry result = new AbstractMap.SimpleImmutableEntry(p);
- deleteEntry(p);
+ Map.Entry result = exportEntry(p);
+ if (p != null)
+ deleteEntry(p);
return result;
}
@@ -723,8 +691,7 @@ public class TreeMap
* @since 1.6
*/
public Map.Entry lowerEntry(K key) {
- Entry e = getLowerEntry(key);
- return (e == null)? null : new AbstractMap.SimpleImmutableEntry(e);
+ return exportEntry(getLowerEntry(key));
}
/**
@@ -735,8 +702,7 @@ public class TreeMap
* @since 1.6
*/
public K lowerKey(K key) {
- Entry e = getLowerEntry(key);
- return (e == null)? null : e.key;
+ return keyOrNull(getLowerEntry(key));
}
/**
@@ -747,8 +713,7 @@ public class TreeMap
* @since 1.6
*/
public Map.Entry floorEntry(K key) {
- Entry e = getFloorEntry(key);
- return (e == null)? null : new AbstractMap.SimpleImmutableEntry(e);
+ return exportEntry(getFloorEntry(key));
}
/**
@@ -759,8 +724,7 @@ public class TreeMap
* @since 1.6
*/
public K floorKey(K key) {
- Entry e = getFloorEntry(key);
- return (e == null)? null : e.key;
+ return keyOrNull(getFloorEntry(key));
}
/**
@@ -771,8 +735,7 @@ public class TreeMap
* @since 1.6
*/
public Map.Entry ceilingEntry(K key) {
- Entry e = getCeilingEntry(key);
- return (e == null)? null : new AbstractMap.SimpleImmutableEntry(e);
+ return exportEntry(getCeilingEntry(key));
}
/**
@@ -783,8 +746,7 @@ public class TreeMap
* @since 1.6
*/
public K ceilingKey(K key) {
- Entry e = getCeilingEntry(key);
- return (e == null)? null : e.key;
+ return keyOrNull(getCeilingEntry(key));
}
/**
@@ -795,8 +757,7 @@ public class TreeMap
* @since 1.6
*/
public Map.Entry higherEntry(K key) {
- Entry e = getHigherEntry(key);
- return (e == null)? null : new AbstractMap.SimpleImmutableEntry(e);
+ return exportEntry(getHigherEntry(key));
}
/**
@@ -807,8 +768,7 @@ public class TreeMap
* @since 1.6
*/
public K higherKey(K key) {
- Entry e = getHigherEntry(key);
- return (e == null)? null : e.key;
+ return keyOrNull(getHigherEntry(key));
}
// Views
@@ -994,10 +954,7 @@ public class TreeMap
}
public boolean contains(Object o) {
- for (Entry e = getFirstEntry(); e != null; e = successor(e))
- if (valEquals(e.getValue(), o))
- return true;
- return false;
+ return TreeMap.this.containsValue(o);
}
public boolean remove(Object o) {
@@ -1064,7 +1021,7 @@ public class TreeMap
}
Iterator descendingKeyIterator() {
- return new DescendingKeyIterator(getFirstEntry());
+ return new DescendingKeyIterator(getLastEntry());
}
static final class KeySet extends AbstractSet implements NavigableSet {
@@ -1110,15 +1067,15 @@ public class TreeMap
return size() != oldSize;
}
public NavigableSet subSet(E fromElement, boolean fromInclusive,
- E toElement, boolean toInclusive) {
- return new TreeSet(m.subMap(fromElement, fromInclusive,
- toElement, toInclusive));
+ E toElement, boolean toInclusive) {
+ return new KeySet(m.subMap(fromElement, fromInclusive,
+ toElement, toInclusive));
}
public NavigableSet headSet(E toElement, boolean inclusive) {
- return new TreeSet(m.headMap(toElement, inclusive));
+ return new KeySet(m.headMap(toElement, inclusive));
}
public NavigableSet tailSet(E fromElement, boolean inclusive) {
- return new TreeSet(m.tailMap(fromElement, inclusive));
+ return new KeySet(m.tailMap(fromElement, inclusive));
}
public SortedSet subSet(E fromElement, E toElement) {
return subSet(fromElement, true, toElement, false);
@@ -1130,7 +1087,7 @@ public class TreeMap
return tailSet(fromElement, true);
}
public NavigableSet descendingSet() {
- return new TreeSet(m.descendingMap());
+ return new KeySet(m.descendingMap());
}
}
@@ -1152,23 +1109,25 @@ public class TreeMap
return next != null;
}
- final Entry nextEntry() {
- Entry e = lastReturned = next;
+ final Entry nextEntry() {
+ Entry e = next;
if (e == null)
throw new NoSuchElementException();
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
next = successor(e);
+ lastReturned = e;
return e;
}
final Entry prevEntry() {
- Entry e = lastReturned= next;
+ Entry e = next;
if (e == null)
throw new NoSuchElementException();
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
next = predecessor(e);
+ lastReturned = e;
return e;
}
@@ -1177,10 +1136,11 @@ public class TreeMap
throw new IllegalStateException();
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
+ // deleted entries are replaced by their successors
if (lastReturned.left != null && lastReturned.right != null)
next = lastReturned;
deleteEntry(lastReturned);
- expectedModCount++;
+ expectedModCount = modCount;
lastReturned = null;
}
}
@@ -1221,16 +1181,69 @@ public class TreeMap
}
}
+ // Little utilities
+
+ /**
+ * Compares two keys using the correct comparison method for this TreeMap.
+ */
+ final int compare(Object k1, Object k2) {
+ return comparator==null ? ((Comparable super K>)k1).compareTo((K)k2)
+ : comparator.compare((K)k1, (K)k2);
+ }
+
+ /**
+ * Test two values for equality. Differs from o1.equals(o2) only in
+ * that it copes with null o1 properly.
+ */
+ final static boolean valEquals(Object o1, Object o2) {
+ return (o1==null ? o2==null : o1.equals(o2));
+ }
+
+ /**
+ * Return SimpleImmutableEntry for entry, or null if null
+ */
+ static Map.Entry exportEntry(TreeMap.Entry e) {
+ return e == null? null :
+ new AbstractMap.SimpleImmutableEntry(e);
+ }
+
+ /**
+ * Return key for entry, or null if null
+ */
+ static K keyOrNull(TreeMap.Entry e) {
+ return e == null? null : e.key;
+ }
+
+ /**
+ * Returns the key corresponding to the specified Entry.
+ * @throws NoSuchElementException if the Entry is null
+ */
+ static K key(Entry e) {
+ if (e==null)
+ throw new NoSuchElementException();
+ return e.key;
+ }
+
+
// SubMaps
+ /**
+ * Dummy value serving as unmatchable fence key for unbounded
+ * SubMapIterators
+ */
+ private static final Object UNBOUNDED = new Object();
+
+ /**
+ * @serial include
+ */
static abstract class NavigableSubMap extends AbstractMap
implements NavigableMap, java.io.Serializable {
- /*
+ /**
* The backing map.
*/
final TreeMap m;
- /*
+ /**
* Endpoints are represented as triples (fromStart, lo,
* loInclusive) and (toEnd, hi, hiInclusive). If fromStart is
* true, then the low (absolute) bound is the start of the
@@ -1238,7 +1251,6 @@ public class TreeMap
* if loInclusive is true, lo is the inclusive bound, else lo
* is the exclusive bound. Similarly for the upper bound.
*/
-
final K lo, hi;
final boolean fromStart, toEnd;
final boolean loInclusive, hiInclusive;
@@ -1298,21 +1310,6 @@ public class TreeMap
return inclusive ? inRange(key) : inClosedRange(key);
}
- /**
- * Return SimpleImmutableEntry for entry, or null if null
- */
- static Map.Entry exportEntry(TreeMap.Entry e) {
- return e == null? null :
- new AbstractMap.SimpleImmutableEntry(e);
- }
-
- /**
- * Return key for entry, or null if null
- */
- static K exportKey(TreeMap.Entry e) {
- return e == null? null : e.key;
- }
-
/*
* Absolute versions of relation operations.
* Subclasses map to these using like-named "sub"
@@ -1320,7 +1317,7 @@ public class TreeMap
*/
final TreeMap.Entry absLowest() {
- TreeMap.Entry e =
+ TreeMap.Entry e =
(fromStart ? m.getFirstEntry() :
(loInclusive ? m.getCeilingEntry(lo) :
m.getHigherEntry(lo)));
@@ -1328,44 +1325,44 @@ public class TreeMap
}
final TreeMap.Entry absHighest() {
- TreeMap.Entry e =
+ TreeMap.Entry e =
(toEnd ? m.getLastEntry() :
(hiInclusive ? m.getFloorEntry(hi) :
m.getLowerEntry(hi)));
return (e == null || tooLow(e.key)) ? null : e;
}
-
+
final TreeMap.Entry absCeiling(K key) {
if (tooLow(key))
return absLowest();
- TreeMap.Entry e = m.getCeilingEntry(key);
+ TreeMap.Entry e = m.getCeilingEntry(key);
return (e == null || tooHigh(e.key)) ? null : e;
}
final TreeMap.Entry absHigher(K key) {
if (tooLow(key))
return absLowest();
- TreeMap.Entry e = m.getHigherEntry(key);
+ TreeMap.Entry e = m.getHigherEntry(key);
return (e == null || tooHigh(e.key)) ? null : e;
}
final TreeMap.Entry absFloor(K key) {
if (tooHigh(key))
return absHighest();
- TreeMap.Entry e = m.getFloorEntry(key);
+ TreeMap.Entry e = m.getFloorEntry(key);
return (e == null || tooLow(e.key)) ? null : e;
}
final TreeMap.Entry absLower(K key) {
if (tooHigh(key))
return absHighest();
- TreeMap.Entry e = m.getLowerEntry(key);
+ TreeMap.Entry e = m.getLowerEntry(key);
return (e == null || tooLow(e.key)) ? null : e;
}
/** Returns the absolute high fence for ascending traversal */
final TreeMap.Entry absHighFence() {
- return (toEnd ? null : (hiInclusive ?
+ return (toEnd ? null : (hiInclusive ?
m.getHigherEntry(hi) :
m.getCeilingEntry(hi)));
}
@@ -1378,7 +1375,7 @@ public class TreeMap
}
// Abstract methods defined in ascending vs descending classes
- // These relay to the appropriate absolute versions
+ // These relay to the appropriate absolute versions
abstract TreeMap.Entry subLowest();
abstract TreeMap.Entry subHighest();
@@ -1426,7 +1423,7 @@ public class TreeMap
}
public final K ceilingKey(K key) {
- return exportKey(subCeiling(key));
+ return keyOrNull(subCeiling(key));
}
public final Map.Entry higherEntry(K key) {
@@ -1434,7 +1431,7 @@ public class TreeMap
}
public final K higherKey(K key) {
- return exportKey(subHigher(key));
+ return keyOrNull(subHigher(key));
}
public final Map.Entry floorEntry(K key) {
@@ -1442,7 +1439,7 @@ public class TreeMap
}
public final K floorKey(K key) {
- return exportKey(subFloor(key));
+ return keyOrNull(subFloor(key));
}
public final Map.Entry lowerEntry(K key) {
@@ -1450,7 +1447,7 @@ public class TreeMap
}
public final K lowerKey(K key) {
- return exportKey(subLower(key));
+ return keyOrNull(subLower(key));
}
public final K firstKey() {
@@ -1470,7 +1467,7 @@ public class TreeMap
}
public final Map.Entry pollFirstEntry() {
- TreeMap.Entry e = subLowest();
+ TreeMap.Entry e = subLowest();
Map.Entry result = exportEntry(e);
if (e != null)
m.deleteEntry(e);
@@ -1478,7 +1475,7 @@ public class TreeMap
}
public final Map.Entry pollLastEntry() {
- TreeMap.Entry e = subHighest();
+ TreeMap.Entry e = subHighest();
Map.Entry result = exportEntry(e);
if (e != null)
m.deleteEntry(e);
@@ -1575,7 +1572,7 @@ public class TreeMap
abstract class SubMapIterator implements Iterator {
TreeMap.Entry lastReturned;
TreeMap.Entry next;
- final K fenceKey;
+ final Object fenceKey;
int expectedModCount;
SubMapIterator(TreeMap.Entry first,
@@ -1583,7 +1580,7 @@ public class TreeMap
expectedModCount = m.modCount;
lastReturned = null;
next = first;
- fenceKey = fence == null ? null : fence.key;
+ fenceKey = fence == null ? UNBOUNDED : fence.key;
}
public final boolean hasNext() {
@@ -1591,36 +1588,50 @@ public class TreeMap
}
final TreeMap.Entry nextEntry() {
- TreeMap.Entry e = lastReturned = next;
+ TreeMap.Entry e = next;
if (e == null || e.key == fenceKey)
throw new NoSuchElementException();
if (m.modCount != expectedModCount)
throw new ConcurrentModificationException();
next = successor(e);
+ lastReturned = e;
return e;
}
final TreeMap.Entry prevEntry() {
- TreeMap.Entry e = lastReturned = next;
+ TreeMap.Entry e = next;
if (e == null || e.key == fenceKey)
throw new NoSuchElementException();
if (m.modCount != expectedModCount)
throw new ConcurrentModificationException();
next = predecessor(e);
+ lastReturned = e;
return e;
}
- public void remove() {
+ final void removeAscending() {
if (lastReturned == null)
throw new IllegalStateException();
if (m.modCount != expectedModCount)
throw new ConcurrentModificationException();
+ // deleted entries are replaced by their successors
if (lastReturned.left != null && lastReturned.right != null)
next = lastReturned;
m.deleteEntry(lastReturned);
- expectedModCount++;
lastReturned = null;
+ expectedModCount = m.modCount;
+ }
+
+ final void removeDescending() {
+ if (lastReturned == null)
+ throw new IllegalStateException();
+ if (m.modCount != expectedModCount)
+ throw new ConcurrentModificationException();
+ m.deleteEntry(lastReturned);
+ lastReturned = null;
+ expectedModCount = m.modCount;
}
+
}
final class SubMapEntryIterator extends SubMapIterator> {
@@ -1631,6 +1642,9 @@ public class TreeMap
public Map.Entry next() {
return nextEntry();
}
+ public void remove() {
+ removeAscending();
+ }
}
final class SubMapKeyIterator extends SubMapIterator {
@@ -1641,6 +1655,9 @@ public class TreeMap
public K next() {
return nextEntry().key;
}
+ public void remove() {
+ removeAscending();
+ }
}
final class DescendingSubMapEntryIterator extends SubMapIterator> {
@@ -1652,6 +1669,9 @@ public class TreeMap
public Map.Entry next() {
return prevEntry();
}
+ public void remove() {
+ removeDescending();
+ }
}
final class DescendingSubMapKeyIterator extends SubMapIterator {
@@ -1662,15 +1682,21 @@ public class TreeMap
public K next() {
return prevEntry().key;
}
+ public void remove() {
+ removeDescending();
+ }
}
}
+ /**
+ * @serial include
+ */
static final class AscendingSubMap extends NavigableSubMap {
private static final long serialVersionUID = 912986545866124060L;
AscendingSubMap(TreeMap m,
boolean fromStart, K lo, boolean loInclusive,
- boolean toEnd, K hi, boolean hiInclusive) {
+ boolean toEnd, K hi, boolean hiInclusive) {
super(m, fromStart, lo, loInclusive, toEnd, hi, hiInclusive);
}
@@ -1679,7 +1705,7 @@ public class TreeMap
}
public NavigableMap subMap(K fromKey, boolean fromInclusive,
- K toKey, boolean toInclusive) {
+ K toKey, boolean toInclusive) {
if (!inRange(fromKey, fromInclusive))
throw new IllegalArgumentException("fromKey out of range");
if (!inRange(toKey, toInclusive))
@@ -1690,7 +1716,7 @@ public class TreeMap
}
public NavigableMap headMap(K toKey, boolean inclusive) {
- if (!inClosedRange(toKey))
+ if (!inRange(toKey, inclusive))
throw new IllegalArgumentException("toKey out of range");
return new AscendingSubMap(m,
fromStart, lo, loInclusive,
@@ -1741,11 +1767,14 @@ public class TreeMap
TreeMap.Entry subLower(K key) { return absLower(key); }
}
+ /**
+ * @serial include
+ */
static final class DescendingSubMap extends NavigableSubMap {
private static final long serialVersionUID = 912986545866120460L;
DescendingSubMap(TreeMap m,
boolean fromStart, K lo, boolean loInclusive,
- boolean toEnd, K hi, boolean hiInclusive) {
+ boolean toEnd, K hi, boolean hiInclusive) {
super(m, fromStart, lo, loInclusive, toEnd, hi, hiInclusive);
}
@@ -1757,7 +1786,7 @@ public class TreeMap
}
public NavigableMap subMap(K fromKey, boolean fromInclusive,
- K toKey, boolean toInclusive) {
+ K toKey, boolean toInclusive) {
if (!inRange(fromKey, fromInclusive))
throw new IllegalArgumentException("fromKey out of range");
if (!inRange(toKey, toInclusive))
@@ -1820,30 +1849,16 @@ public class TreeMap
}
/**
- * Compares two keys using the correct comparison method for this TreeMap.
- */
- final int compare(Object k1, Object k2) {
- return comparator==null ? ((Comparable super K>)k1).compareTo((K)k2)
- : comparator.compare((K)k1, (K)k2);
- }
-
- /**
- * Test two values for equality. Differs from o1.equals(o2) only in
- * that it copes with null o1 properly.
- */
- final static boolean valEquals(Object o1, Object o2) {
- return (o1==null ? o2==null : o1.equals(o2));
- }
-
- /**
* This class exists solely for the sake of serialization
* compatibility with previous releases of TreeMap that did not
* support NavigableMap. It translates an old-version SubMap into
* a new-version AscendingSubMap. This class is never otherwise
* used.
+ *
+ * @serial include
*/
private class SubMap extends AbstractMap
- implements SortedMap, java.io.Serializable {
+ implements SortedMap, java.io.Serializable {
private static final long serialVersionUID = -6520786458950516097L;
private boolean fromStart = false, toEnd = false;
private K fromKey, toKey;
@@ -1862,6 +1877,8 @@ public class TreeMap
}
+ // Red-black mechanics
+
private static final boolean RED = false;
private static final boolean BLACK = true;
@@ -1871,7 +1888,7 @@ public class TreeMap
*/
static final class Entry implements Map.Entry {
- K key;
+ K key;
V value;
Entry left = null;
Entry right = null;
@@ -1922,7 +1939,7 @@ public class TreeMap
public boolean equals(Object o) {
if (!(o instanceof Map.Entry))
return false;
- Map.Entry e = (Map.Entry)o;
+ Map.Entry,?> e = (Map.Entry,?>)o;
return valEquals(key,e.getKey()) && valEquals(value,e.getValue());
}
@@ -2026,7 +2043,7 @@ public class TreeMap
private static void setColor(Entry p, boolean c) {
if (p != null)
- p.color = c;
+ p.color = c;
}
private static Entry leftOf(Entry p) {
@@ -2037,40 +2054,43 @@ public class TreeMap
return (p == null) ? null: p.right;
}
- /** From CLR **/
+ /** From CLR */
private void rotateLeft(Entry p) {
- Entry r = p.right;
- p.right = r.left;
- if (r.left != null)
- r.left.parent = p;
- r.parent = p.parent;
- if (p.parent == null)
- root = r;
- else if (p.parent.left == p)
- p.parent.left = r;
- else
- p.parent.right = r;
- r.left = p;
- p.parent = r;
+ if (p != null) {
+ Entry r = p.right;
+ p.right = r.left;
+ if (r.left != null)
+ r.left.parent = p;
+ r.parent = p.parent;
+ if (p.parent == null)
+ root = r;
+ else if (p.parent.left == p)
+ p.parent.left = r;
+ else
+ p.parent.right = r;
+ r.left = p;
+ p.parent = r;
+ }
}
- /** From CLR **/
+ /** From CLR */
private void rotateRight(Entry p) {
- Entry l = p.left;
- p.left = l.right;
- if (l.right != null) l.right.parent = p;
- l.parent = p.parent;
- if (p.parent == null)
- root = l;
- else if (p.parent.right == p)
- p.parent.right = l;
- else p.parent.left = l;
- l.right = p;
- p.parent = l;
+ if (p != null) {
+ Entry l = p.left;
+ p.left = l.right;
+ if (l.right != null) l.right.parent = p;
+ l.parent = p.parent;
+ if (p.parent == null)
+ root = l;
+ else if (p.parent.right == p)
+ p.parent.right = l;
+ else p.parent.left = l;
+ l.right = p;
+ p.parent = l;
+ }
}
-
- /** From CLR **/
+ /** From CLR */
private void fixAfterInsertion(Entry x) {
x.color = RED;
@@ -2089,8 +2109,7 @@ public class TreeMap
}
setColor(parentOf(x), BLACK);
setColor(parentOf(parentOf(x)), RED);
- if (parentOf(parentOf(x)) != null)
- rotateRight(parentOf(parentOf(x)));
+ rotateRight(parentOf(parentOf(x)));
}
} else {
Entry y = leftOf(parentOf(parentOf(x)));
@@ -2106,8 +2125,7 @@ public class TreeMap
}
setColor(parentOf(x), BLACK);
setColor(parentOf(parentOf(x)), RED);
- if (parentOf(parentOf(x)) != null)
- rotateLeft(parentOf(parentOf(x)));
+ rotateLeft(parentOf(parentOf(x)));
}
}
}
@@ -2117,14 +2135,14 @@ public class TreeMap
/**
* Delete node p, and then rebalance the tree.
*/
-
private void deleteEntry(Entry p) {
- decrementSize();
+ modCount++;
+ size--;
// If strictly internal, copy successor's element to p and then make p
// point to successor.
if (p.left != null && p.right != null) {
- Entry s = successor (p);
+ Entry s = successor(p);
p.key = s.key;
p.value = s.value;
p = s;
@@ -2165,7 +2183,7 @@ public class TreeMap
}
}
- /** From CLR **/
+ /** From CLR */
private void fixAfterDeletion(Entry x) {
while (x != root && colorOf(x) == BLACK) {
if (x == leftOf(parentOf(x))) {
@@ -2273,19 +2291,19 @@ public class TreeMap
buildFromSorted(size, null, s, null);
}
- /** Intended to be called only from TreeSet.readObject **/
+ /** Intended to be called only from TreeSet.readObject */
void readTreeSet(int size, java.io.ObjectInputStream s, V defaultVal)
throws java.io.IOException, ClassNotFoundException {
buildFromSorted(size, null, s, defaultVal);
}
- /** Intended to be called only from TreeSet.addAll **/
+ /** Intended to be called only from TreeSet.addAll */
void addAllForTreeSet(SortedSet extends K> set, V defaultVal) {
- try {
- buildFromSorted(set.size(), set.iterator(), null, defaultVal);
- } catch (java.io.IOException cannotHappen) {
- } catch (ClassNotFoundException cannotHappen) {
- }
+ try {
+ buildFromSorted(set.size(), set.iterator(), null, defaultVal);
+ } catch (java.io.IOException cannotHappen) {
+ } catch (ClassNotFoundException cannotHappen) {
+ }
}
@@ -2320,12 +2338,12 @@ public class TreeMap
* This cannot occur if str is null.
*/
private void buildFromSorted(int size, Iterator it,
- java.io.ObjectInputStream str,
- V defaultVal)
+ java.io.ObjectInputStream str,
+ V defaultVal)
throws java.io.IOException, ClassNotFoundException {
this.size = size;
root = buildFromSorted(0, 0, size-1, computeRedLevel(size),
- it, str, defaultVal);
+ it, str, defaultVal);
}
/**
@@ -2343,10 +2361,10 @@ public class TreeMap
* Must be equal to computeRedLevel for tree of this size.
*/
private final Entry buildFromSorted(int level, int lo, int hi,
- int redLevel,
- Iterator it,
- java.io.ObjectInputStream str,
- V defaultVal)
+ int redLevel,
+ Iterator it,
+ java.io.ObjectInputStream str,
+ V defaultVal)
throws java.io.IOException, ClassNotFoundException {
/*
* Strategy: The root is the middlemost element. To get to it, we
@@ -2362,12 +2380,12 @@ public class TreeMap
if (hi < lo) return null;
- int mid = (lo + hi) / 2;
+ int mid = (lo + hi) >>> 1;
Entry left = null;
if (lo < mid)
left = buildFromSorted(level+1, lo, mid - 1, redLevel,
- it, str, defaultVal);
+ it, str, defaultVal);
// extract key and/or value from iterator or stream
K key;
@@ -2399,7 +2417,7 @@ public class TreeMap
if (mid < hi) {
Entry right = buildFromSorted(level+1, mid+1, hi, redLevel,
- it, str, defaultVal);
+ it, str, defaultVal);
middle.right = right;
right.parent = middle;
}