blob: e3dc5a70565927ebbf141ce7c85a23fe1bd5a55f [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package java.util;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
/**
* TreeMap is an implementation of SortedMap. All optional operations (adding
* and removing) are supported. The values can be any objects. The keys can be
* any objects which are comparable to each other either using their natural
* order or a specified Comparator.
*
* @since Android 1.0
*/
public class TreeMap<K, V> extends AbstractMap<K, V> implements SortedMap<K, V>, Cloneable,
Serializable {
private static final long serialVersionUID = 919286545866124006L;
transient int size;
transient Entry<K, V> root;
private Comparator<? super K> comparator;
transient int modCount;
transient Set<Map.Entry<K, V>> entrySet;
/**
* Entry is an internal class which is used to hold the entries of a
* TreeMap.
*/
static class Entry<K, V> extends MapEntry<K, V> {
Entry<K, V> parent, left, right;
boolean color;
Entry(K key) {
super(key);
}
Entry(K key, V value) {
super(key, value);
}
@SuppressWarnings("unchecked")
Entry<K, V> clone(Entry<K, V> parent) {
Entry<K, V> clone = (Entry<K, V>) super.clone();
clone.parent = parent;
if (left != null) {
clone.left = left.clone(clone);
}
if (right != null) {
clone.right = right.clone(clone);
}
return clone;
}
}
@SuppressWarnings("unchecked")
private static <T> Comparable<T> toComparable(T obj) {
return (Comparable<T>)obj;
}
private static class AbstractMapIterator <K,V> {
TreeMap<K, V> backingMap;
int expectedModCount;
TreeMap.Entry<K, V> node;
TreeMap.Entry<K, V> lastNode;
AbstractMapIterator(TreeMap<K, V> map, Entry<K, V> startNode) {
backingMap = map;
expectedModCount = map.modCount;
node = startNode;
}
public boolean hasNext() {
return node != null;
}
final public void remove() {
if (expectedModCount == backingMap.modCount) {
if (lastNode != null) {
backingMap.rbDelete(lastNode);
lastNode = null;
expectedModCount++;
} else {
throw new IllegalStateException();
}
} else {
throw new ConcurrentModificationException();
}
}
final void makeNext() {
if (expectedModCount != backingMap.modCount) {
throw new ConcurrentModificationException();
} else if (node == null) {
throw new NoSuchElementException();
}
lastNode = node;
node = TreeMap.successor(node);
}
}
private static class UnboundedEntryIterator <K, V> extends AbstractMapIterator<K, V> implements Iterator<Map.Entry<K, V>> {
UnboundedEntryIterator(TreeMap<K, V> map, Entry<K, V> startNode) {
super(map, startNode);
}
UnboundedEntryIterator(TreeMap<K, V> map) {
super(map, map.root == null ? null : TreeMap.minimum(map.root));
}
public Map.Entry<K, V> next() {
makeNext();
return lastNode;
}
}
static class UnboundedKeyIterator <K, V> extends AbstractMapIterator<K, V> implements Iterator<K> {
public UnboundedKeyIterator(TreeMap<K, V> treeMap, Entry<K, V> entry) {
super(treeMap, entry);
}
public UnboundedKeyIterator(TreeMap<K, V> map) {
super(map, map.root == null ? null : TreeMap.minimum(map.root));
}
public K next() {
makeNext();
return lastNode.key;
}
}
static class UnboundedValueIterator <K, V> extends AbstractMapIterator<K, V> implements Iterator<V> {
public UnboundedValueIterator(TreeMap<K, V> treeMap, Entry<K, V> startNode) {
super(treeMap, startNode);
}
public UnboundedValueIterator(TreeMap<K, V> map) {
super(map, map.root == null ? null : TreeMap.minimum(map.root));
}
public V next() {
makeNext();
return lastNode.value;
}
}
private static class ComparatorBoundedIterator<K, V> extends AbstractMapIterator<K, V> {
private final K endKey;
private final Comparator<? super K> cmp;
ComparatorBoundedIterator(TreeMap<K, V> map, Entry<K, V> startNode, K end) {
super(map, startNode);
endKey = end;
cmp = map.comparator();
}
final void cleanNext() {
if (node != null && cmp.compare(endKey, node.key) <= 0) {
node = null;
}
}
@Override
public boolean hasNext() {
return (node != null && endKey != null) && (cmp.compare(node.key, endKey) < 0);
}
}
private static class ComparatorBoundedEntryIterator<K, V> extends
ComparatorBoundedIterator<K, V> implements Iterator<Map.Entry<K, V>> {
ComparatorBoundedEntryIterator(TreeMap<K, V> map, Entry<K, V> startNode, K end) {
super(map, startNode, end);
}
public Map.Entry<K, V> next() {
makeNext();
cleanNext();
return lastNode;
}
}
private static class ComparatorBoundedKeyIterator<K, V> extends
ComparatorBoundedIterator<K, V> implements Iterator<K> {
ComparatorBoundedKeyIterator(TreeMap<K, V> map, Entry<K, V> startNode, K end) {
super(map, startNode, end);
}
public K next() {
makeNext();
cleanNext();
return lastNode.key;
}
}
private static class ComparatorBoundedValueIterator<K, V> extends
ComparatorBoundedIterator<K, V> implements Iterator<V> {
ComparatorBoundedValueIterator(TreeMap<K, V> map, Entry<K, V> startNode, K end) {
super(map, startNode, end);
}
public V next() {
makeNext();
cleanNext();
return lastNode.value;
}
}
private static class ComparableBoundedIterator<K, V> extends AbstractMapIterator<K, V> {
private final Comparable<K> endKey;
public ComparableBoundedIterator(TreeMap<K, V> treeMap, Entry<K, V> entry,
Comparable<K> endKey) {
super(treeMap, entry);
this.endKey = endKey;
}
final void cleanNext() {
if ((node != null) && (endKey.compareTo(node.key) <= 0)) {
node = null;
}
}
@Override
public boolean hasNext() {
return (node != null) && (endKey.compareTo(node.key) > 0);
}
}
private static class ComparableBoundedEntryIterator<K, V> extends
ComparableBoundedIterator<K, V> implements Iterator<Map.Entry<K, V>> {
ComparableBoundedEntryIterator(TreeMap<K, V> map, Entry<K, V> startNode,
Comparable<K> end) {
super(map, startNode, end);
}
public Map.Entry<K, V> next() {
makeNext();
cleanNext();
return lastNode;
}
}
private static class ComparableBoundedKeyIterator<K, V> extends
ComparableBoundedIterator<K, V> implements Iterator<K> {
ComparableBoundedKeyIterator(TreeMap<K, V> map, Entry<K, V> startNode, Comparable<K> end) {
super(map, startNode, end);
}
public K next() {
makeNext();
cleanNext();
return lastNode.key;
}
}
private static class ComparableBoundedValueIterator<K, V> extends
ComparableBoundedIterator<K, V> implements Iterator<V> {
ComparableBoundedValueIterator(TreeMap<K, V> map, Entry<K, V> startNode,
Comparable<K> end) {
super(map, startNode, end);
}
public V next() {
makeNext();
cleanNext();
return lastNode.value;
}
}
static final class SubMap<K,V> extends AbstractMap<K,V> implements SortedMap<K,V>, Serializable {
private static final long serialVersionUID = -6520786458950516097L;
private TreeMap<K,V> backingMap;
boolean hasStart, hasEnd;
K startKey, endKey;
transient Set<Map.Entry<K,V>> entrySet = null;
SubMap(K start, TreeMap<K,V> map) {
backingMap = map;
hasStart = true;
startKey = start;
}
SubMap(K start, TreeMap<K,V> map, K end) {
backingMap = map;
hasStart = hasEnd = true;
startKey = start;
endKey = end;
}
SubMap(TreeMap<K,V> map, K end) {
backingMap = map;
hasEnd = true;
endKey = end;
}
private void checkRange(K key) {
Comparator<? super K> cmp = backingMap.comparator;
if (cmp == null) {
Comparable<K> object = toComparable(key);
if (hasStart && object.compareTo(startKey) < 0) {
throw new IllegalArgumentException();
}
if (hasEnd && object.compareTo(endKey) > 0) {
throw new IllegalArgumentException();
}
} else {
if (hasStart
&& backingMap.comparator().compare(key, startKey) < 0) {
throw new IllegalArgumentException();
}
if (hasEnd && backingMap.comparator().compare(key, endKey) > 0) {
throw new IllegalArgumentException();
}
}
}
private boolean isInRange(K key) {
Comparator<? super K> cmp = backingMap.comparator;
if (cmp == null) {
Comparable<K> object = toComparable(key);
if (hasStart && object.compareTo(startKey) < 0) {
return false;
}
if (hasEnd && object.compareTo(endKey) >= 0) {
return false;
}
} else {
if (hasStart && cmp.compare(key, startKey) < 0) {
return false;
}
if (hasEnd && cmp.compare(key, endKey) >= 0) {
return false;
}
}
return true;
}
private boolean checkUpperBound(K key) {
if (hasEnd) {
Comparator<? super K> cmp = backingMap.comparator;
if (cmp == null) {
return (toComparable(key).compareTo(endKey) < 0);
}
return (cmp.compare(key, endKey) < 0);
}
return true;
}
private boolean checkLowerBound(K key) {
if (hasStart) {
Comparator<? super K> cmp = backingMap.comparator;
if (cmp == null) {
return (toComparable(key).compareTo(startKey) >= 0);
}
return (cmp.compare(key, startKey) >= 0);
}
return true;
}
public Comparator<? super K> comparator() {
return backingMap.comparator();
}
@SuppressWarnings("unchecked")
@Override
public boolean containsKey(Object key) {
if (isInRange((K)key)) {
return backingMap.containsKey(key);
}
return false;
}
@Override
public Set<Map.Entry<K,V>> entrySet() {
if(entrySet==null) {
entrySet = new SubMapEntrySet<K,V>(this);
}
return entrySet;
}
public K firstKey() {
TreeMap.Entry<K,V> node = firstEntry();
if (node != null ) {
return node.key;
}
throw new NoSuchElementException();
}
TreeMap.Entry<K,V> firstEntry() {
if (!hasStart) {
TreeMap.Entry<K,V> root = backingMap.root;
return (root == null) ? null : minimum(backingMap.root);
}
TreeMap.Entry<K,V> node = backingMap.findAfter(startKey);
if (node != null && checkUpperBound(node.key)) {
return node;
}
return null;
}
@SuppressWarnings("unchecked")
@Override
public V get(Object key) {
if (isInRange((K)key)) {
return backingMap.get(key);
}
return null;
}
public SortedMap<K,V> headMap(K endKey) {
checkRange(endKey);
if (hasStart) {
return new SubMap<K,V>(startKey, backingMap, endKey);
}
return new SubMap<K,V>(backingMap, endKey);
}
@Override
public boolean isEmpty() {
if (hasStart) {
TreeMap.Entry<K,V> node = backingMap.findAfter(startKey);
return node == null || !checkUpperBound(node.key);
}
return backingMap.findBefore(endKey) == null;
}
@Override
public Set<K> keySet() {
if (keySet == null) {
keySet = new SubMapKeySet<K,V>(this);
}
return keySet;
}
public K lastKey() {
if (!hasEnd) {
return backingMap.lastKey();
}
TreeMap.Entry<K,V> node = backingMap.findBefore(endKey);
if (node != null && checkLowerBound(node.key)) {
return node.key;
}
throw new NoSuchElementException();
}
@Override
public V put(K key, V value) {
if (isInRange(key)) {
return backingMap.put(key, value);
}
throw new IllegalArgumentException();
}
@SuppressWarnings("unchecked")
@Override
public V remove(Object key) {
if (isInRange((K)key)) {
return backingMap.remove(key);
}
return null;
}
public SortedMap<K,V> subMap(K startKey, K endKey) {
checkRange(startKey);
checkRange(endKey);
Comparator<? super K> c = backingMap.comparator();
if (c == null) {
if (toComparable(startKey).compareTo(endKey) <= 0) {
return new SubMap<K,V>(startKey, backingMap, endKey);
}
} else {
if (c.compare(startKey, endKey) <= 0) {
return new SubMap<K,V>(startKey, backingMap, endKey);
}
}
throw new IllegalArgumentException();
}
public SortedMap<K,V> tailMap(K startKey) {
checkRange(startKey);
if (hasEnd) {
return new SubMap<K,V>(startKey, backingMap, endKey);
}
return new SubMap<K,V>(startKey, backingMap);
}
@Override
public Collection<V> values() {
if(valuesCollection==null) {
valuesCollection = new SubMapValuesCollection<K,V>(this);
}
return valuesCollection;
}
}
static class SubMapEntrySet<K,V> extends AbstractSet<Map.Entry<K,V>> implements Set<Map.Entry<K,V>> {
SubMap<K,V> subMap;
SubMapEntrySet(SubMap<K,V> map) {
subMap = map;
}
@Override
public boolean isEmpty() {
return subMap.isEmpty();
}
@Override
public Iterator<Map.Entry<K,V>> iterator() {
TreeMap.Entry<K,V> startNode = subMap.firstEntry();
if (subMap.hasEnd) {
Comparator<? super K> cmp = subMap.comparator();
if (cmp == null) {
return new ComparableBoundedEntryIterator<K,V>(subMap.backingMap, startNode, toComparable(subMap.endKey));
}
return new ComparatorBoundedEntryIterator<K,V>(subMap.backingMap, startNode, subMap.endKey);
}
return new UnboundedEntryIterator<K,V>(subMap.backingMap, startNode);
}
@Override
public int size() {
int size = 0;
Iterator<Map.Entry<K,V>> it = iterator();
while (it.hasNext()) {
size++;
it.next();
}
return size;
}
@SuppressWarnings("unchecked")
@Override
public boolean contains(Object object) {
if (object instanceof Map.Entry) {
Map.Entry<K,V> entry = (Map.Entry<K,V>) object;
K key = entry.getKey();
if (subMap.isInRange(key)) {
V v1 = subMap.get(key), v2 = entry.getValue();
return v1 == null ? v2 == null : v1.equals(v2);
}
}
return false;
}
}
static class SubMapKeySet<K,V> extends AbstractSet<K> implements Set<K> {
SubMap<K,V> subMap;
SubMapKeySet(SubMap<K,V> map) {
subMap = map;
}
@Override
public boolean contains(Object object) {
return subMap.containsKey(object);
}
@Override
public boolean isEmpty() {
return subMap.isEmpty();
}
@Override
public int size() {
int size = 0;
Iterator<K> it = iterator();
while (it.hasNext()) {
size++;
it.next();
}
return size;
}
@Override
public Iterator<K> iterator() {
TreeMap.Entry<K,V> startNode = subMap.firstEntry();
if (subMap.hasEnd) {
Comparator<? super K> cmp = subMap.comparator();
if (cmp == null) {
return new ComparableBoundedKeyIterator<K,V>(subMap.backingMap, startNode, toComparable(subMap.endKey));
}
return new ComparatorBoundedKeyIterator<K,V>(subMap.backingMap, startNode, subMap.endKey);
}
return new UnboundedKeyIterator<K,V>(subMap.backingMap, startNode);
}
}
static class SubMapValuesCollection<K,V> extends AbstractCollection<V> {
SubMap<K,V> subMap;
public SubMapValuesCollection(SubMap<K,V> subMap) {
this.subMap = subMap;
}
@Override
public boolean isEmpty() {
return subMap.isEmpty();
}
@Override
public Iterator<V> iterator() {
TreeMap.Entry<K,V> startNode = subMap.firstEntry();
if (subMap.hasEnd) {
Comparator<? super K> cmp = subMap.comparator();
if (cmp == null) {
return new ComparableBoundedValueIterator<K,V>(subMap.backingMap, startNode, toComparable(subMap.endKey));
}
return new ComparatorBoundedValueIterator<K,V>(subMap.backingMap, startNode, subMap.endKey);
}
return new UnboundedValueIterator<K,V>(subMap.backingMap, startNode);
}
@Override
public int size() {
int cnt = 0;
for (Iterator<V> it = iterator(); it.hasNext();) {
it.next();
cnt++;
}
return cnt;
}
}
/**
* Constructs a new empty {@code TreeMap} instance.
*
* @since Android 1.0
*/
public TreeMap() {
super();
}
/**
* Constructs a new empty {@code TreeMap} instance with the specified
* comparator.
*
* @param comparator
* the comparator to compare keys with.
* @since Android 1.0
*/
public TreeMap(Comparator<? super K> comparator) {
this.comparator = comparator;
}
/**
* Constructs a new {@code TreeMap} instance containing the mappings from
* the specified map and using natural ordering.
*
* @param map
* the mappings to add.
* @throws ClassCastException
* if a key in the specified map does not implement the
* Comparable interface, or if the keys in the map cannot be
* compared.
* @since Android 1.0
*/
public TreeMap(Map<? extends K,? extends V> map) {
this();
putAll(map);
}
/**
* Constructs a new {@code TreeMap} instance containing the mappings from
* the specified SortedMap and using the same comparator.
*
* @param map
* the mappings to add.
* @since Android 1.0
*/
public TreeMap(SortedMap<K,? extends V> map) {
this(map.comparator());
Iterator<? extends Map.Entry<K, ? extends V>> it = map.entrySet().iterator();
if (it.hasNext()) {
Map.Entry<K, ? extends V> entry = it.next();
Entry<K, V> last = new Entry<K, V>(entry.getKey(), entry.getValue());
root = last;
size = 1;
while (it.hasNext()) {
entry = it.next();
Entry<K, V> x = new Entry<K, V>(entry.getKey(), entry.getValue());
x.parent = last;
last.right = x;
size++;
balance(x);
last = x;
}
}
}
void balance(Entry<K, V> x) {
Entry<K, V> y;
x.color = true;
while (x != root && x.parent.color) {
if (x.parent == x.parent.parent.left) {
y = x.parent.parent.right;
if (y != null && y.color) {
x.parent.color = false;
y.color = false;
x.parent.parent.color = true;
x = x.parent.parent;
} else {
if (x == x.parent.right) {
x = x.parent;
leftRotate(x);
}
x.parent.color = false;
x.parent.parent.color = true;
rightRotate(x.parent.parent);
}
} else {
y = x.parent.parent.left;
if (y != null && y.color) {
x.parent.color = false;
y.color = false;
x.parent.parent.color = true;
x = x.parent.parent;
} else {
if (x == x.parent.left) {
x = x.parent;
rightRotate(x);
}
x.parent.color = false;
x.parent.parent.color = true;
leftRotate(x.parent.parent);
}
}
}
root.color = false;
}
/**
* Removes all mappings from this TreeMap, leaving it empty.
*
* @see Map#isEmpty()
* @see #size()
* @since Android 1.0
*/
@Override
public void clear() {
root = null;
size = 0;
modCount++;
}
/**
* Returns a new {@code TreeMap} with the same mappings, size and comparator
* as this instance.
*
* @return a shallow copy of this instance.
* @see java.lang.Cloneable
* @since Android 1.0
*/
@SuppressWarnings("unchecked")
@Override
public Object clone() {
try {
TreeMap<K, V> clone = (TreeMap<K, V>) super.clone();
clone.entrySet = null;
if (root != null) {
clone.root = root.clone(null);
}
return clone;
} catch (CloneNotSupportedException e) {
return null;
}
}
/**
* Returns the comparator used to compare elements in this map.
*
* @return the comparator or {@code null} if the natural ordering is used.
* @since Android 1.0
*/
public Comparator<? super K> comparator() {
return comparator;
}
/**
* Returns whether this map contains the specified key.
*
* @param key
* the key to search for.
* @return {@code true} if this map contains the specified key,
* {@code false} otherwise.
* @since Android 1.0
*/
@Override
public boolean containsKey(Object key) {
return find(key) != null;
}
/**
* Returns whether this map contains the specified value.
*
* @param value
* the value to search for.
* @return {@code true} if this map contains the specified value,
* {@code false} otherwise.
* @since Android 1.0
*/
@Override
public boolean containsValue(Object value) {
if (root != null) {
return containsValue(root, value);
}
return false;
}
private boolean containsValue(Entry<K, V> node, Object value) {
if (value == null ? node.value == null : value.equals(node.value)) {
return true;
}
if (node.left != null) {
if (containsValue(node.left, value)) {
return true;
}
}
if (node.right != null) {
if (containsValue(node.right, value)) {
return true;
}
}
return false;
}
/**
* Returns a set containing all of the mappings in this map. Each mapping is
* an instance of {@link Map.Entry}. As the set is backed by this map,
* changes in one will be reflected in the other. It does not support adding
* operations.
*
* @return a set of the mappings.
* @since Android 1.0
*/
@Override
public Set<Map.Entry<K, V>> entrySet() {
if (entrySet == null) {
entrySet = new AbstractSet<Map.Entry<K, V>>() {
@Override
public int size() {
return size;
}
@Override
public void clear() {
TreeMap.this.clear();
}
@SuppressWarnings("unchecked")
@Override
public boolean contains(Object object) {
if (object instanceof Map.Entry) {
Map.Entry<K, V> entry = (Map.Entry<K, V>) object;
Object v1 = get(entry.getKey()), v2 = entry.getValue();
return v1 == null ? v2 == null : v1.equals(v2);
}
return false;
}
@Override
public Iterator<Map.Entry<K, V>> iterator() {
return new UnboundedEntryIterator<K, V>(TreeMap.this);
}
};
}
return entrySet;
}
@SuppressWarnings("unchecked")
private Entry<K, V> find(Object keyObj) {
int result;
K key = (K)keyObj;
Comparable<K> object = null;
if (comparator == null) {
object = toComparable(key);
}
Entry<K, V> x = root;
while (x != null) {
result = object != null ? object.compareTo(x.key) : comparator
.compare(key, x.key);
if (result == 0) {
return x;
}
x = result < 0 ? x.left : x.right;
}
return null;
}
@SuppressWarnings("unchecked")
Entry<K, V> findAfter(Object keyObj) {
K key = (K)keyObj;
int result;
Comparable<K> object = null;
if (comparator == null) {
object = toComparable(key);
}
Entry<K, V> x = root, last = null;
while (x != null) {
result = object != null ? object.compareTo(x.key) : comparator
.compare(key, x.key);
if (result == 0) {
return x;
}
if (result < 0) {
last = x;
x = x.left;
} else {
x = x.right;
}
}
return last;
}
Entry<K, V> findBefore(K key) {
int result;
Comparable<K> object = null;
if (comparator == null) {
object = toComparable(key);
}
Entry<K, V> x = root, last = null;
while (x != null) {
result = object != null ? object.compareTo(x.key) : comparator
.compare(key, x.key);
if (result <= 0) {
x = x.left;
} else {
last = x;
x = x.right;
}
}
return last;
}
/**
* Returns the first key in this map.
*
* @return the first key in this map.
* @exception NoSuchElementException
* if this sorted map is empty.
* @since Android 1.0
*/
public K firstKey() {
if (root != null) {
return minimum(root).key;
}
throw new NoSuchElementException();
}
private void fixup(Entry<K, V> x) {
Entry<K, V> w;
while (x != root && !x.color) {
if (x == x.parent.left) {
w = x.parent.right;
if (w == null) {
x = x.parent;
continue;
}
if (w.color) {
w.color = false;
x.parent.color = true;
leftRotate(x.parent);
w = x.parent.right;
if (w == null) {
x = x.parent;
continue;
}
}
if ((w.left == null || !w.left.color)
&& (w.right == null || !w.right.color)) {
w.color = true;
x = x.parent;
} else {
if (w.right == null || !w.right.color) {
w.left.color = false;
w.color = true;
rightRotate(w);
w = x.parent.right;
}
w.color = x.parent.color;
x.parent.color = false;
w.right.color = false;
leftRotate(x.parent);
x = root;
}
} else {
w = x.parent.left;
if (w == null) {
x = x.parent;
continue;
}
if (w.color) {
w.color = false;
x.parent.color = true;
rightRotate(x.parent);
w = x.parent.left;
if (w == null) {
x = x.parent;
continue;
}
}
if ((w.left == null || !w.left.color)
&& (w.right == null || !w.right.color)) {
w.color = true;
x = x.parent;
} else {
if (w.left == null || !w.left.color) {
w.right.color = false;
w.color = true;
leftRotate(w);
w = x.parent.left;
}
w.color = x.parent.color;
x.parent.color = false;
w.left.color = false;
rightRotate(x.parent);
x = root;
}
}
}
x.color = false;
}
/**
* Returns the value of the mapping with the specified key.
*
* @param key
* the key.
* @return the value of the mapping with the specified key.
* @throws ClassCastException
* if the key cannot be compared with the keys in this map.
* @throws NullPointerException
* if the key is {@code null} and the comparator cannot handle
* {@code null}.
* @since Android 1.0
*/
@Override
public V get(Object key) {
Entry<K, V> node = find(key);
if (node != null) {
return node.value;
}
return null;
}
/**
* Returns a sorted map over a range of this sorted map with all keys that
* are less than the specified {@code endKey}. Changes to the returned
* sorted map are reflected in this sorted map and vice versa.
* <p>
* Note: The returned map will not allow an insertion of a key outside the
* specified range.
* </p>
*
* @param endKey
* the high boundary of the range specified.
* @return a sorted map where the keys are less than {@code endKey}.
* @throws ClassCastException
* if the specified key cannot be compared with the keys in this
* map.
* @throws NullPointerException
* if the specified key is {@code null} and the comparator
* cannot handle {@code null} keys.
* @throws IllegalArgumentException
* if this map is itself a sorted map over a range of another
* map and the specified key is outside of its range.
* @since Android 1.0
*/
public SortedMap<K, V> headMap(K endKey) {
// Check for errors
if (comparator == null) {
toComparable(endKey).compareTo(endKey);
} else {
comparator.compare(endKey, endKey);
}
return new SubMap<K, V>(this, endKey);
}
/**
* Returns a set of the keys contained in this map. The set is backed by
* this map so changes to one are reflected by the other. The set does not
* support adding.
*
* @return a set of the keys.
* @since Android 1.0
*/
@Override
public Set<K> keySet() {
if (keySet == null) {
keySet = new AbstractSet<K>() {
@Override
public boolean contains(Object object) {
return containsKey(object);
}
@Override
public int size() {
return size;
}
@Override
public void clear() {
TreeMap.this.clear();
}
@Override
public Iterator<K> iterator() {
return new UnboundedKeyIterator<K,V> (TreeMap.this);
}
};
}
return keySet;
}
/**
* Returns the last key in this map.
*
* @return the last key in this map.
* @throws NoSuchElementException
* if this map is empty.
* @since Android 1.0
*/
public K lastKey() {
if (root != null) {
return maximum(root).key;
}
throw new NoSuchElementException();
}
private void leftRotate(Entry<K, V> x) {
Entry<K, V> y = x.right;
x.right = y.left;
if (y.left != null) {
y.left.parent = x;
}
y.parent = x.parent;
if (x.parent == null) {
root = y;
} else {
if (x == x.parent.left) {
x.parent.left = y;
} else {
x.parent.right = y;
}
}
y.left = x;
x.parent = y;
}
static <K, V> Entry<K, V> maximum(Entry<K, V> x) {
while (x.right != null) {
x = x.right;
}
return x;
}
static <K, V> Entry<K, V> minimum(Entry<K, V> x) {
while (x.left != null) {
x = x.left;
}
return x;
}
static <K, V> Entry<K, V> predecessor(Entry<K, V> x) {
if (x.left != null) {
return maximum(x.left);
}
Entry<K, V> y = x.parent;
while (y != null && x == y.left) {
x = y;
y = y.parent;
}
return y;
}
/**
* Maps the specified key to the specified value.
*
* @param key
* the key.
* @param value
* the value.
* @return the value of any previous mapping with the specified key or
* {@code null} if there was no mapping.
* @throws ClassCastException
* if the specified key cannot be compared with the keys in this
* map.
* @throws NullPointerException
* if the specified key is {@code null} and the comparator
* cannot handle {@code null} keys.
* @since Android 1.0
*/
@Override
public V put(K key, V value) {
MapEntry<K, V> entry = rbInsert(key);
V result = entry.value;
entry.value = value;
return result;
}
/**
* Copies all the mappings in the given map to this map. These mappings will
* replace all mappings that this map had for any of the keys currently in
* the given map.
*
* @param map
* the map to copy mappings from.
* @throws ClassCastException
* if a key in the specified map cannot be compared with the
* keys in this map.
* @throws NullPointerException
* if a key in the specified map is {@code null} and the
* comparator cannot handle {@code null} keys.
* @since Android 1.0
*/
@Override
public void putAll(Map<? extends K, ? extends V> map) {
super.putAll(map);
}
void rbDelete(Entry<K, V> z) {
Entry<K, V> y = z.left == null || z.right == null ? z : successor(z);
Entry<K, V> x = y.left != null ? y.left : y.right;
if (x != null) {
x.parent = y.parent;
}
if (y.parent == null) {
root = x;
} else if (y == y.parent.left) {
y.parent.left = x;
} else {
y.parent.right = x;
}
modCount++;
if (y != z) {
z.key = y.key;
z.value = y.value;
}
if (!y.color && root != null) {
if (x == null) {
fixup(y.parent);
} else {
fixup(x);
}
}
size--;
}
private Entry<K, V> rbInsert(K object) {
int result = 0;
Entry<K, V> y = null;
if (size != 0) {
Comparable<K> key = null;
if (comparator == null) {
key = toComparable(object);
}
Entry<K, V> x = root;
while (x != null) {
y = x;
result = key != null ? key.compareTo(x.key) : comparator
.compare(object, x.key);
if (result == 0) {
return x;
}
x = result < 0 ? x.left : x.right;
}
}
size++;
modCount++;
Entry<K, V> z = new Entry<K, V>(object);
if (y == null) {
return root = z;
}
z.parent = y;
if (result < 0) {
y.left = z;
} else {
y.right = z;
}
balance(z);
return z;
}
/**
* Removes the mapping with the specified key from this map.
*
* @param key
* the key of the mapping to remove.
* @return the value of the removed mapping or {@code null} if no mapping
* for the specified key was found.
* @throws ClassCastException
* if the specified key cannot be compared with the keys in this
* map.
* @throws NullPointerException
* if the specified key is {@code null} and the comparator
* cannot handle {@code null} keys.
* @since Android 1.0
*/
@Override
public V remove(Object key) {
if (size == 0) {
return null;
}
Entry<K, V> node = find(key);
if (node == null) {
return null;
}
V result = node.value;
rbDelete(node);
return result;
}
private void rightRotate(Entry<K, V> x) {
Entry<K, V> y = x.left;
x.left = y.right;
if (y.right != null) {
y.right.parent = x;
}
y.parent = x.parent;
if (x.parent == null) {
root = y;
} else {
if (x == x.parent.right) {
x.parent.right = y;
} else {
x.parent.left = y;
}
}
y.right = x;
x.parent = y;
}
/**
* Returns the number of mappings in this map.
*
* @return the number of mappings in this map.
* @since Android 1.0
*/
@Override
public int size() {
return size;
}
/**
* Returns a sorted map over a range of this sorted map with all keys
* greater than or equal to the specified {@code startKey} and less than the
* specified {@code endKey}. Changes to the returned sorted map are
* reflected in this sorted map and vice versa.
* <p>
* Note: The returned map will not allow an insertion of a key outside the
* specified range.
* </p>
*
* @param startKey
* the low boundary of the range (inclusive).
* @param endKey
* the high boundary of the range (exclusive),
* @return a sorted map with the key from the specified range.
* @throws ClassCastException
* if the start or end key cannot be compared with the keys in
* this map.
* @throws NullPointerException
* if the start or end key is {@code null} and the comparator
* cannot handle {@code null} keys.
* @throws IllegalArgumentException
* if the start key is greater than the end key, or if this map
* is itself a sorted map over a range of another sorted map and
* the specified range is outside of its range.
* @since Android 1.0
*/
public SortedMap<K, V> subMap(K startKey, K endKey) {
if (comparator == null) {
if (toComparable(startKey).compareTo(endKey) <= 0) {
return new SubMap<K, V>(startKey, this, endKey);
}
} else {
if (comparator.compare(startKey, endKey) <= 0) {
return new SubMap<K, V>(startKey, this, endKey);
}
}
throw new IllegalArgumentException();
}
static <K, V> Entry<K, V> successor(Entry<K, V> x) {
if (x.right != null) {
return minimum(x.right);
}
Entry<K, V> y = x.parent;
while (y != null && x == y.right) {
x = y;
y = y.parent;
}
return y;
}
/**
* Returns a sorted map over a range of this sorted map with all keys that
* are greater than or equal to the specified {@code startKey}. Changes to
* the returned sorted map are reflected in this sorted map and vice versa.
* <p>
* Note: The returned map will not allow an insertion of a key outside the
* specified range.
* </p>
*
* @param startKey
* the low boundary of the range specified.
* @return a sorted map where the keys are greater or equal to
* {@code startKey}.
* @throws ClassCastException
* if the specified key cannot be compared with the keys in this
* map.
* @throws NullPointerException
* if the specified key is {@code null} and the comparator
* cannot handle {@code null} keys.
* @throws IllegalArgumentException
* if this map itself a sorted map over a range of another map
* and the specified key is outside of its range.
* @since Android 1.0
*/
public SortedMap<K, V> tailMap(K startKey) {
// Check for errors
if (comparator == null) {
toComparable(startKey).compareTo(startKey);
} else {
comparator.compare(startKey, startKey);
}
return new SubMap<K, V>(startKey, this);
}
/**
* Returns a collection of the values contained in this map. The collection
* is backed by this map so changes to one are reflected by the other. The
* collection supports remove, removeAll, retainAll and clear operations,
* and it does not support add or addAll operations.
* <p>
* This method returns a collection which is the subclass of
* AbstractCollection. The iterator method of this subclass returns a
* "wrapper object" over the iterator of map's entrySet(). The {@code size}
* method wraps the map's size method and the {@code contains} method wraps
* the map's containsValue method.
* </p>
* <p>
* The collection is created when this method is called for the first time
* and returned in response to all subsequent calls. This method may return
* different collections when multiple concurrent calls occur, since no
* synchronization is performed.
* </p>
*
* @return a collection of the values contained in this map.
* @since Android 1.0
*/
@Override
public Collection<V> values() {
if (valuesCollection == null) {
valuesCollection = new AbstractCollection<V>() {
@Override
public boolean contains(Object object) {
return containsValue(object);
}
@Override
public int size() {
return size;
}
@Override
public void clear() {
TreeMap.this.clear();
}
@Override
public Iterator<V> iterator() {
return new UnboundedValueIterator<K,V> (TreeMap.this);
}
};
}
return valuesCollection;
}
private void writeObject(ObjectOutputStream stream) throws IOException {
stream.defaultWriteObject();
stream.writeInt(size);
if (size > 0) {
Entry<K, V> node = minimum(root);
while (node != null) {
stream.writeObject(node.key);
stream.writeObject(node.value);
node = successor(node);
}
}
}
@SuppressWarnings("unchecked")
private void readObject(ObjectInputStream stream) throws IOException,
ClassNotFoundException {
stream.defaultReadObject();
size = stream.readInt();
Entry<K, V> last = null;
for (int i = size; --i >= 0;) {
Entry<K, V> node = new Entry<K, V>((K)stream.readObject());
node.value = (V)stream.readObject();
if (last == null) {
root = node;
} else {
node.parent = last;
last.right = node;
balance(node);
}
last = node;
}
}
}