blob: 9d1e22097768fbbcea4036ee08c3a052bfe7adb5 [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 1.2
*/
public class TreeMap <K, V> extends AbstractMap<K, V> implements SortedMap<K, V>,
Cloneable, Serializable {
private static final long serialVersionUID = 919286545866124006L;
transient int size;
private Comparator<? super K> comparator;
transient int modCount;
transient Set<Map.Entry<K, V>> entrySet;
transient Node<K, V> root;
class MapEntry implements Map.Entry<K, V>, Cloneable {
final int offset;
final Node<K, V> node;
final K key;
MapEntry(Node<K, V> node, int offset) {
this.node = node;
this.offset = offset;
key = node.keys[offset];
}
@Override
public Object clone() {
try {
return super.clone();
} catch (CloneNotSupportedException e) {
return null;
}
}
@Override
public boolean equals(Object object) {
if (this == object) {
return true;
}
if (object instanceof Map.Entry) {
Map.Entry<?, ?> entry = (Map.Entry<?, ?>) object;
V value = getValue();
return (key == null ? entry.getKey() == null : key.equals(entry
.getKey()))
&& (value == null ? entry.getValue() == null : value
.equals(entry.getValue()));
}
return false;
}
public K getKey() {
return key;
}
public V getValue() {
if (node.keys[offset] == key) {
return node.values[offset];
}
if (containsKey(key)) {
return get(key);
}
throw new IllegalStateException();
}
@Override
public int hashCode() {
V value = getValue();
return (key == null ? 0 : key.hashCode())
^ (value == null ? 0 : value.hashCode());
}
public V setValue(V object) {
if (node.keys[offset] == key) {
V res = node.values[offset];
node.values[offset] = object;
return res;
}
if (containsKey(key)) {
return put(key, object);
}
throw new IllegalStateException();
}
@Override
public String toString() {
return key + "=" + getValue();
}
}
static class Node <K,V> implements Cloneable {
static final int NODE_SIZE = 64;
Node<K, V> prev, next;
Node<K, V> parent, left, right;
V[] values;
K[] keys;
int left_idx = 0;
int right_idx = -1;
int size = 0;
boolean color;
public Node() {
keys = (K[]) new Object[NODE_SIZE];
values = (V[]) new Object[NODE_SIZE];
}
@SuppressWarnings("unchecked")
Node<K, V> clone(Node<K, V> parent) throws CloneNotSupportedException {
Node<K, V> clone = (Node<K, V>) super.clone();
clone.keys = (K[]) new Object[NODE_SIZE];
clone.values = (V[]) new Object[NODE_SIZE];
System.arraycopy(keys, 0, clone.keys, 0, keys.length);
System.arraycopy(values, 0, clone.values, 0, values.length);
clone.left_idx = left_idx;
clone.right_idx = right_idx;
clone.parent = parent;
if (left != null) {
clone.left = left.clone(clone);
}
if (right != null) {
clone.right = right.clone(clone);
}
clone.prev = null;
clone.next = null;
return clone;
}
}
@SuppressWarnings("unchecked")
private static <T> Comparable<T> toComparable(T obj) {
if (obj == null) {
throw new NullPointerException();
}
return (Comparable) obj;
}
static class AbstractMapIterator <K,V> {
TreeMap<K, V> backingMap;
int expectedModCount;
Node<K, V> node;
Node<K, V> lastNode;
int offset;
int lastOffset;
AbstractMapIterator(TreeMap<K, V> map, Node<K, V> startNode, int startOffset) {
backingMap = map;
expectedModCount = map.modCount;
node = startNode;
offset = startOffset;
}
AbstractMapIterator(TreeMap<K, V> map, Node<K, V> startNode) {
this(map, startNode, startNode != null ?
startNode.right_idx - startNode.left_idx : 0);
}
AbstractMapIterator(TreeMap<K, V> map) {
this(map, minimum(map.root));
}
public boolean hasNext() {
return node != null;
}
final void makeNext() {
if (expectedModCount != backingMap.modCount) {
throw new ConcurrentModificationException();
} else if (node == null) {
throw new NoSuchElementException();
}
lastNode = node;
lastOffset = offset;
if (offset != 0) {
offset--;
} else {
node = node.next;
if (node != null) {
offset = node.right_idx - node.left_idx;
}
}
}
final public void remove() {
if (expectedModCount == backingMap.modCount) {
if (lastNode != null) {
int idx = lastNode.right_idx - lastOffset;
backingMap.removeFromIterator(lastNode, idx);
lastNode = null;
expectedModCount++;
} else {
throw new IllegalStateException();
}
} else {
throw new ConcurrentModificationException();
}
}
}
static class UnboundedEntryIterator <K, V> extends AbstractMapIterator<K, V>
implements Iterator<Map.Entry<K, V>> {
UnboundedEntryIterator(TreeMap<K, V> map, Node<K, V> startNode, int startOffset) {
super(map, startNode, startOffset);
}
UnboundedEntryIterator(TreeMap<K, V> map) {
super(map);
}
public Map.Entry<K, V> next() {
makeNext();
int idx = lastNode.right_idx - lastOffset;
return backingMap.new MapEntry(lastNode, idx);
}
}
static class UnboundedKeyIterator <K, V> extends AbstractMapIterator<K, V>
implements Iterator<K> {
UnboundedKeyIterator(TreeMap<K, V> map, Node<K, V> startNode, int startOffset) {
super(map, startNode, startOffset);
}
UnboundedKeyIterator(TreeMap<K, V> map) {
super(map);
}
public K next() {
makeNext();
return lastNode.keys[lastNode.right_idx - lastOffset];
}
}
static class UnboundedValueIterator <K, V> extends AbstractMapIterator<K, V>
implements Iterator<V> {
UnboundedValueIterator(TreeMap<K, V> map, Node<K, V> startNode, int startOffset) {
super(map, startNode, startOffset);
}
UnboundedValueIterator(TreeMap<K, V> map) {
super(map);
}
public V next() {
makeNext();
return lastNode.values[lastNode.right_idx - lastOffset];
}
}
static class BoundedMapIterator <K, V> extends AbstractMapIterator<K, V> {
Node<K, V> finalNode;
int finalOffset;
BoundedMapIterator(Node<K, V> startNode, int startOffset, TreeMap<K, V> map,
Node<K, V> finalNode, int finalOffset) {
super(map, finalNode==null? null : startNode, startOffset);
this.finalNode = finalNode;
this.finalOffset = finalOffset;
}
BoundedMapIterator(Node<K, V> startNode, TreeMap<K, V> map,
Node<K, V> finalNode, int finalOffset) {
this(startNode, startNode != null ?
startNode.right_idx - startNode.left_idx : 0,
map, finalNode, finalOffset);
}
BoundedMapIterator(Node<K, V> startNode, int startOffset,
TreeMap<K, V> map, Node<K, V> finalNode) {
this(startNode, startOffset, map, finalNode,
finalNode.right_idx - finalNode.left_idx);
}
void makeBoundedNext() {
makeNext();
if (lastNode == finalNode && lastOffset == finalOffset) {
node = null;
}
}
}
static class BoundedEntryIterator <K, V> extends BoundedMapIterator<K, V>
implements Iterator<Map.Entry<K, V>> {
public BoundedEntryIterator(Node<K, V> startNode, int startOffset, TreeMap<K, V> map,
Node<K, V> finalNode, int finalOffset) {
super(startNode, startOffset, map, finalNode, finalOffset);
}
public Map.Entry<K, V> next() {
makeBoundedNext();
int idx = lastNode.right_idx - lastOffset;
return backingMap.new MapEntry(lastNode, idx);
}
}
static class BoundedKeyIterator <K, V> extends BoundedMapIterator<K, V>
implements Iterator<K> {
public BoundedKeyIterator(Node<K, V> startNode, int startOffset, TreeMap<K, V> map,
Node<K, V> finalNode, int finalOffset) {
super(startNode, startOffset, map, finalNode, finalOffset);
}
public K next() {
makeBoundedNext();
return lastNode.keys[lastNode.right_idx - lastOffset];
}
}
static class BoundedValueIterator <K, V> extends BoundedMapIterator<K, V>
implements Iterator<V> {
public BoundedValueIterator(Node<K, V> startNode, int startOffset, TreeMap<K, V> map,
Node<K, V> finalNode, int finalOffset) {
super(startNode, startOffset, map, finalNode, finalOffset);
}
public V next() {
makeBoundedNext();
return lastNode.values[lastNode.right_idx - lastOffset];
}
}
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;
transient int firstKeyModCount = -1;
transient int lastKeyModCount = -1;
transient Node<K, V> firstKeyNode;
transient int firstKeyIndex;
transient Node<K, V> lastKeyNode;
transient int lastKeyIndex;
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 void clear() {
keySet().clear();
}
@Override
public boolean containsValue(Object value) {
Iterator<V> it = values().iterator();
if (value != null) {
while (it.hasNext()) {
if (value.equals(it.next())) {
return true;
}
}
} else {
while (it.hasNext()) {
if (it.next() == null) {
return true;
}
}
}
return false;
}
@Override
public Set<Map.Entry<K, V>> entrySet() {
if (entrySet == null) {
entrySet = new SubMapEntrySet<K, V>(this);
}
return entrySet;
}
private void setFirstKey() {
if (firstKeyModCount == backingMap.modCount) {
return;
}
Comparable<K> object = backingMap.comparator == null ?
toComparable((K) startKey) : null;
K key = (K) startKey;
Node<K, V> node = backingMap.root;
Node<K, V> foundNode = null;
int foundIndex = -1;
TOP_LOOP:
while (node != null) {
K[] keys = node.keys;
int left_idx = node.left_idx;
int result = backingMap.cmp(object, key, keys[left_idx]);
if (result < 0) {
foundNode = node;
foundIndex = left_idx;
node = node.left;
} else if (result == 0) {
foundNode = node;
foundIndex = left_idx;
break;
} else {
int right_idx = node.right_idx;
if (left_idx != right_idx) {
result = backingMap.cmp(object, key, keys[right_idx]);
}
if (result > 0) {
node = node.right;
} else if (result == 0) {
foundNode = node;
foundIndex = right_idx;
break;
} else { /*search in node*/
foundNode = node;
foundIndex = right_idx;
int low = left_idx + 1, mid = 0, high = right_idx - 1;
while (low <= high) {
mid = (low + high) >>> 1;
result = backingMap.cmp(object, key, keys[mid]);
if (result > 0) {
low = mid + 1;
} else if (result == 0) {
foundNode = node;
foundIndex = mid;
break TOP_LOOP;
} else {
foundNode = node;
foundIndex = mid;
high = mid - 1;
}
}
break TOP_LOOP;
}
}
}
if (foundNode != null && !checkUpperBound(foundNode.keys[foundIndex])) {
foundNode = null;
}
firstKeyNode = foundNode;
firstKeyIndex = foundIndex;
firstKeyModCount = backingMap.modCount;
}
public K firstKey() {
if (backingMap.size > 0) {
if (!hasStart) {
Node<K, V> node = minimum(backingMap.root);
if (node != null && checkUpperBound(node.keys[node.left_idx])) {
return node.keys[node.left_idx];
}
} else {
setFirstKey();
if (firstKeyNode != null) {
return firstKeyNode.keys[firstKeyIndex];
}
}
}
throw new NoSuchElementException();
}
@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) {
setFirstKey();
return firstKeyNode == null;
} else {
setLastKey();
return lastKeyNode == null;
}
}
@Override
public Set<K> keySet() {
if (keySet == null) {
keySet = new SubMapKeySet<K, V>(this);
}
return keySet;
}
private void setLastKey() {
if (lastKeyModCount == backingMap.modCount) {
return;
}
Comparable<K> object = backingMap.comparator == null ?
toComparable((K) endKey) : null;
K key = (K) endKey;
Node<K, V> node = backingMap.root;
Node<K, V> foundNode = null;
int foundIndex = -1;
TOP_LOOP:
while (node != null) {
K[] keys = node.keys;
int left_idx = node.left_idx;
int result = backingMap.cmp(object, key, keys[left_idx]);
if (result <= 0) {
node = node.left;
} else {
int right_idx = node.right_idx;
if (left_idx != right_idx) {
result = backingMap.cmp(object, key, keys[right_idx]);
}
if (result > 0) {
foundNode = node;
foundIndex = right_idx;
node = node.right;
} else if (result == 0) {
if (node.left_idx == node.right_idx) {
foundNode = node.prev;
if (foundNode != null) {
foundIndex = foundNode.right_idx - 1;
}
} else {
foundNode = node;
foundIndex = right_idx - 1;
}
break;
} else { /*search in node*/
foundNode = node;
foundIndex = left_idx;
int low = left_idx + 1, mid = 0, high = right_idx - 1;
while (low <= high) {
mid = (low + high) >>> 1;
result = backingMap.cmp(object, key, keys[mid]);
if (result > 0) {
foundNode = node;
foundIndex = mid;
low = mid + 1;
} else if (result == 0) {
foundNode = node;
foundIndex = mid - 1;
break TOP_LOOP;
} else {
high = mid - 1;
}
}
break TOP_LOOP;
}
}
}
if (foundNode != null && !checkLowerBound(foundNode.keys[foundIndex])) {
foundNode = null;
}
lastKeyNode = foundNode;
lastKeyIndex = foundIndex;
lastKeyModCount = backingMap.modCount;
}
public K lastKey() {
if (backingMap.size > 0) {
if (!hasEnd) {
Node<K, V> node = maximum(backingMap.root);
if (node != null && checkLowerBound(node.keys[node.right_idx])) {
return node.keys[node.right_idx];
}
} else {
setLastKey();
if (lastKeyNode != null) {
return lastKeyNode.keys[lastKeyIndex];
}
}
}
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;
}
public int size() {
Node<K, V> from, to;
int fromIndex, toIndex;
if (hasStart) {
setFirstKey();
from = firstKeyNode;
fromIndex = firstKeyIndex;
} else {
from = minimum(backingMap.root);
fromIndex = from == null ? 0 : from.left_idx;
}
if (from == null) {
return 0;
}
if (hasEnd) {
setLastKey();
to = lastKeyNode;
toIndex = lastKeyIndex;
} else {
to = maximum(backingMap.root);
toIndex = to == null ? 0 : to.right_idx;
}
if (to == null) {
return 0;
}
if (from == to) {
return toIndex - fromIndex + 1;
}
int sum = 0;
while (from != to) {
sum += (from.right_idx - fromIndex + 1);
from = from.next;
fromIndex = from.left_idx;
}
return sum + toIndex - fromIndex + 1;
}
private void readObject(ObjectInputStream stream) throws IOException,
ClassNotFoundException {
stream.defaultReadObject();
firstKeyModCount = -1;
lastKeyModCount = -1;
}
}
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();
}
public Iterator<Map.Entry<K, V>> iterator() {
Node<K, V> from;
int fromIndex;
if (subMap.hasStart) {
subMap.setFirstKey();
from = subMap.firstKeyNode;
fromIndex = subMap.firstKeyIndex;
} else {
from = minimum(subMap.backingMap.root);
fromIndex = from != null ? from.left_idx : 0;
}
if (!subMap.hasEnd) {
return new UnboundedEntryIterator<K, V>(subMap.backingMap, from, from == null ? 0 : from.right_idx - fromIndex);
}
subMap.setLastKey();
Node<K, V> to = subMap.lastKeyNode;
int toIndex = subMap.lastKeyIndex;
return new BoundedEntryIterator<K, V>(from, from == null ? 0 : from.right_idx - fromIndex, subMap.backingMap, to, to == null ? 0 : to.right_idx - toIndex);
}
@Override
public int size() {
return subMap.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 && subMap.containsKey(key) ) : v1.equals(v2);
}
}
return false;
}
@Override
public boolean remove(Object object) {
if (contains(object)) {
Map.Entry<K, V> entry = (Map.Entry<K, V>) object;
K key = entry.getKey();
subMap.remove(key);
return true;
}
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() {
return subMap.size();
}
@Override
public boolean remove(Object object) {
if (subMap.containsKey(object)) {
subMap.remove(object);
return true;
}
return false;
}
public Iterator<K> iterator() {
Node<K, V> from;
int fromIndex;
if (subMap.hasStart) {
subMap.setFirstKey();
from = subMap.firstKeyNode;
fromIndex = subMap.firstKeyIndex;
} else {
from = minimum(subMap.backingMap.root);
fromIndex = from != null ? from.left_idx : 0;
}
if (!subMap.hasEnd) {
return new UnboundedKeyIterator<K, V>(subMap.backingMap, from,
from == null ? 0 : from.right_idx - fromIndex);
}
subMap.setLastKey();
Node<K, V> to = subMap.lastKeyNode;
int toIndex = subMap.lastKeyIndex;
return new BoundedKeyIterator<K, V>(from,
from == null ? 0 : from.right_idx - fromIndex, subMap.backingMap, to,
to == null ? 0 : to.right_idx - toIndex);
}
}
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() {
Node<K, V> from;
int fromIndex;
if (subMap.hasStart) {
subMap.setFirstKey();
from = subMap.firstKeyNode;
fromIndex = subMap.firstKeyIndex;
} else {
from = minimum(subMap.backingMap.root);
fromIndex = from != null ? from.left_idx : 0;
}
if (!subMap.hasEnd) {
return new UnboundedValueIterator<K, V>(subMap.backingMap, from,
from == null ? 0 : from.right_idx - fromIndex);
}
subMap.setLastKey();
Node<K, V> to = subMap.lastKeyNode;
int toIndex = subMap.lastKeyIndex;
return new BoundedValueIterator<K, V>(from,
from == null ? 0 : from.right_idx - fromIndex, subMap.backingMap, to,
to == null ? 0 : to.right_idx - toIndex);
}
@Override
public int size() {
return subMap.size();
}
}
/**
* Constructs a new empty {@code TreeMap} instance.
*/
public TreeMap() {
}
/**
* Constructs a new empty {@code TreeMap} instance with the specified
* comparator.
*
* @param comparator
* the comparator to compare keys with.
*/
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.
*/
public TreeMap(Map<? extends K, ? extends V> map) {
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.
*/
public TreeMap(SortedMap<K, ? extends V> map) {
this(map.comparator());
Node<K, V> lastNode = null;
Iterator<? extends Map.Entry<K, ? extends V>> it = map.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<K, ? extends V> entry = it.next();
lastNode = addToLast(lastNode, entry.getKey(), entry.getValue());
}
}
Node<K, V> addToLast(Node<K, V> last, K key, V value) {
if (last == null) {
root = last = createNode(key, value);
size = 1;
} else if (last.size == Node.NODE_SIZE) {
Node<K, V> newNode = createNode(key, value);
attachToRight(last, newNode);
balance(newNode);
size++;
last = newNode;
} else {
appendFromRight(last, key, value);
size++;
}
return last;
}
/**
* Removes all mappings from this TreeMap, leaving it empty.
*
* @see Map#isEmpty()
* @see #size()
*/
@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
*/
@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);
// restore prev/next chain
Node<K, V> node = minimum(clone.root);
while (true) {
Node<K, V> nxt = successor(node);
if (nxt == null) {
break;
}
nxt.prev = node;
node.next = nxt;
node = nxt;
}
}
return clone;
} catch (CloneNotSupportedException e) {
return null;
}
}
static private <K, V> Node<K, V> successor(Node<K, V> x) {
if (x.right != null) {
return minimum(x.right);
}
Node<K, V> y = x.parent;
while (y != null && x == y.right) {
x = y;
y = y.parent;
}
return y;
}
/**
* Returns the comparator used to compare elements in this map.
*
* @return the comparator or {@code null} if the natural ordering is used.
*/
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.
* @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.
*/
@Override
public boolean containsKey(Object key) {
Comparable<K> object = comparator == null ? toComparable((K) key) : null;
K keyK = (K) key;
Node<K, V> node = root;
while (node != null) {
K[] keys = node.keys;
int left_idx = node.left_idx;
int result = cmp(object, keyK, keys[left_idx]);
if (result < 0) {
node = node.left;
} else if (result == 0) {
return true;
} else {
int right_idx = node.right_idx;
if (left_idx != right_idx) {
result = cmp(object, keyK, keys[right_idx]);
}
if (result > 0) {
node = node.right;
} else if (result == 0) {
return true;
} else { /*search in node*/
int low = left_idx + 1, mid = 0, high = right_idx - 1;
while (low <= high) {
mid = (low + high) >>> 1;
result = cmp(object, keyK, keys[mid]);
if (result > 0) {
low = mid + 1;
} else if (result == 0) {
return true;
} else {
high = mid - 1;
}
}
return false;
}
}
}
return false;
}
/**
* 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.
*/
@Override
public boolean containsValue(Object value) {
if (root == null) {
return false;
}
Node<K, V> node = minimum(root);
if (value != null) {
while (node != null) {
int to = node.right_idx;
V[] values = node.values;
for (int i = node.left_idx; i <= to; i++) {
if (value.equals(values[i])) {
return true;
}
}
node = node.next;
}
} else {
while (node != null) {
int to = node.right_idx;
V[] values = node.values;
for (int i = node.left_idx; i <= to; i++) {
if (values[i] == null) {
return true;
}
}
node = node.next;
}
}
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.
*/
@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;
K key = entry.getKey();
Object v1 = TreeMap.this.get(key), v2 = entry.getValue();
return v1 == null ? ( v2 == null && TreeMap.this.containsKey(key) ) : v1.equals(v2);
}
return false;
}
@Override
public boolean remove(Object object) {
if (contains(object)) {
Map.Entry<K, V> entry = (Map.Entry<K, V>) object;
K key = entry.getKey();
TreeMap.this.remove(key);
return true;
}
return false;
}
@Override
public Iterator<Map.Entry<K, V>> iterator() {
return new UnboundedEntryIterator<K, V>(TreeMap.this);
}
};
}
return entrySet;
}
/**
* Returns the first key in this map.
*
* @return the first key in this map.
* @throws NoSuchElementException
* if this map is empty.
*/
public K firstKey() {
if (root != null) {
Node<K, V> node = minimum(root);
return node.keys[node.left_idx];
}
throw new NoSuchElementException();
}
/**
* 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}.
*/
@Override
public V get(Object key) {
Comparable<K> object = comparator == null ? toComparable((K) key) : null;
K keyK = (K) key;
Node<K, V> node = root;
while (node != null) {
K[] keys = node.keys;
int left_idx = node.left_idx;
int result = cmp(object, keyK, keys[left_idx]);
if (result < 0) {
node = node.left;
} else if (result == 0) {
return node.values[left_idx];
} else {
int right_idx = node.right_idx;
if (left_idx != right_idx) {
result = cmp(object, keyK, keys[right_idx]);
}
if (result > 0) {
node = node.right;
} else if (result == 0) {
return node.values[right_idx];
} else { /*search in node*/
int low = left_idx + 1, mid = 0, high = right_idx - 1;
while (low <= high) {
mid = (low + high) >>> 1;
result = cmp(object, keyK, keys[mid]);
if (result > 0) {
low = mid + 1;
} else if (result == 0) {
return node.values[mid];
} else {
high = mid - 1;
}
}
return null;
}
}
}
return null;
}
private int cmp(Comparable<K> object, K key1, K key2) {
return object != null ?
object.compareTo(key2) : comparator.compare(key1, key2);
}
/**
* 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.
*
* @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.
*/
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.
*/
@Override
public Set<K> keySet() {
if (keySet == null) {
keySet = new AbstractSet<K>() {
@Override
public boolean contains(Object object) {
return TreeMap.this.containsKey(object);
}
@Override
public int size() {
return TreeMap.this.size;
}
@Override
public void clear() {
TreeMap.this.clear();
}
@Override
public boolean remove(Object object) {
if (contains(object)) {
TreeMap.this.remove(object);
return true;
}
return false;
}
@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.
*/
public K lastKey() {
if (root != null) {
Node<K, V> node = maximum(root);
return node.keys[node.right_idx];
}
throw new NoSuchElementException();
}
static <K,V> Node<K, V> minimum(Node<K, V> x) {
if (x == null) {
return null;
}
while (x.left != null) {
x = x.left;
}
return x;
}
static <K,V> Node<K, V> maximum(Node<K, V> x) {
if (x == null) {
return null;
}
while (x.right != null) {
x = x.right;
}
return x;
}
/**
* 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.
*/
@Override
public V put(K key, V value) {
if (root == null) {
root = createNode(key, value);
size = 1;
modCount++;
return null;
}
Comparable<K> object = comparator == null ? toComparable((K) key) : null;
K keyK = (K) key;
Node<K, V> node = root;
Node<K, V> prevNode = null;
int result = 0;
while (node != null) {
prevNode = node;
K[] keys = node.keys;
int left_idx = node.left_idx;
result = cmp(object, keyK, keys[left_idx]);
if (result < 0) {
node = node.left;
} else if (result == 0) {
V res = node.values[left_idx];
node.values[left_idx] = value;
return res;
} else {
int right_idx = node.right_idx;
if (left_idx != right_idx) {
result = cmp(object, keyK, keys[right_idx]);
}
if (result > 0) {
node = node.right;
} else if (result == 0) {
V res = node.values[right_idx];
node.values[right_idx] = value;
return res;
} else { /*search in node*/
int low = left_idx + 1, mid = 0, high = right_idx - 1;
while (low <= high) {
mid = (low + high) >>> 1;
result = cmp(object, keyK, keys[mid]);
if (result > 0) {
low = mid + 1;
} else if (result == 0) {
V res = node.values[mid];
node.values[mid] = value;
return res;
} else {
high = mid - 1;
}
}
result = low;
break;
}
}
} /* while */
/*
if(node == null) {
if(prevNode==null) {
- case of empty Tree
} else {
result < 0 - prevNode.left==null - attach here
result > 0 - prevNode.right==null - attach here
}
} else {
insert into node.
result - index where it should be inserted.
}
*/
size++;
modCount++;
if (node == null) {
if (prevNode == null) {
// case of empty Tree
root = createNode(key, value);
} else if (prevNode.size < Node.NODE_SIZE) {
// there is a place for insert
if (result < 0) {
appendFromLeft(prevNode, key, value);
} else {
appendFromRight(prevNode, key, value);
}
} else {
// create and link
Node<K, V> newNode = createNode(key, value);
if (result < 0) {
attachToLeft(prevNode, newNode);
} else {
attachToRight(prevNode, newNode);
}
balance(newNode);
}
} else {
// insert into node.
// result - index where it should be inserted.
if (node.size < Node.NODE_SIZE) { // insert and ok
int left_idx = node.left_idx;
int right_idx = node.right_idx;
if (left_idx == 0 || ((right_idx != Node.NODE_SIZE - 1) && (right_idx - result <= result - left_idx))) {
int right_idxPlus1 = right_idx + 1;
System.arraycopy(node.keys, result, node.keys, result + 1, right_idxPlus1 - result);
System.arraycopy(node.values, result, node.values, result + 1, right_idxPlus1 - result);
node.right_idx = right_idxPlus1;
node.keys[result] = key;
node.values[result] = value;
} else {
int left_idxMinus1 = left_idx - 1;
System.arraycopy(node.keys, left_idx, node.keys, left_idxMinus1, result - left_idx);
System.arraycopy(node.values, left_idx, node.values, left_idxMinus1, result - left_idx);
node.left_idx = left_idxMinus1;
node.keys[result - 1] = key;
node.values[result - 1] = value;
}
node.size++;
} else {
// there are no place here
// insert and push old pair
Node<K, V> previous = node.prev;
Node<K, V> nextNode = node.next;
boolean removeFromStart;
boolean attachFromLeft = false;
Node<K, V> attachHere = null;
if (previous == null) {
if (nextNode != null && nextNode.size < Node.NODE_SIZE) {
// move last pair to next
removeFromStart = false;
} else {
// next node doesn't exist or full
// left==null
// drop first pair to new node from left
removeFromStart = true;
attachFromLeft = true;
attachHere = node;
}
} else if (nextNode == null) {
if (previous.size < Node.NODE_SIZE) {
// move first pair to prev
removeFromStart = true;
} else {
// right == null;
// drop last pair to new node from right
removeFromStart = false;
attachFromLeft = false;
attachHere = node;
}
} else {
if (previous.size < Node.NODE_SIZE) {
if (nextNode.size < Node.NODE_SIZE) {
// choose prev or next for moving
removeFromStart = previous.size < nextNode.size;
} else {
// move first pair to prev
removeFromStart = true;
}
} else {
if (nextNode.size < Node.NODE_SIZE) {
// move last pair to next
removeFromStart = false;
} else {
// prev & next are full
// if node.right!=null then node.next.left==null
// if node.left!=null then node.prev.right==null
if (node.right == null) {
attachHere = node;
attachFromLeft = false;
removeFromStart = false;
} else {
attachHere = nextNode;
attachFromLeft = true;
removeFromStart = false;
}
}
}
}
K movedKey;
V movedValue;
if (removeFromStart) {
// node.left_idx == 0
movedKey = node.keys[0];
movedValue = node.values[0];
int resMunus1 = result - 1;
System.arraycopy(node.keys, 1, node.keys, 0, resMunus1);
System.arraycopy(node.values, 1, node.values, 0, resMunus1);
node.keys [resMunus1] = key;
node.values[resMunus1] = value;
} else {
// node.right_idx == Node.NODE_SIZE - 1
movedKey = node.keys[Node.NODE_SIZE - 1];
movedValue = node.values[Node.NODE_SIZE - 1];
System.arraycopy(node.keys, result, node.keys, result + 1, Node.NODE_SIZE - 1 - result);
System.arraycopy(node.values, result, node.values, result + 1, Node.NODE_SIZE - 1 - result);
node.keys[result] = key;
node.values[result] = value;
}
if (attachHere == null) {
if (removeFromStart) {
appendFromRight(previous, movedKey, movedValue);
} else {
appendFromLeft(nextNode, movedKey, movedValue);
}
} else {
Node<K, V> newNode = createNode(movedKey, movedValue);
if (attachFromLeft) {
attachToLeft(attachHere, newNode);
} else {
attachToRight(attachHere, newNode);
}
balance(newNode);
}
}
}
return null;
}
private void appendFromLeft(Node<K, V> node, K keyObj, V value) {
if (node.left_idx == 0) {
int new_right = node.right_idx + 1;
System.arraycopy(node.keys, 0, node.keys, 1, new_right);
System.arraycopy(node.values, 0, node.values, 1, new_right);
node.right_idx = new_right;
} else {
node.left_idx--;
}
node.size++;
node.keys[node.left_idx] = keyObj;
node.values[node.left_idx] = value;
}
private void attachToLeft(Node<K, V> node, Node<K, V> newNode) {
newNode.parent = node;
// node.left==null - attach here
node.left = newNode;
Node<K, V> predecessor = node.prev;
newNode.prev = predecessor;
newNode.next = node;
if (predecessor != null) {
predecessor.next = newNode;
}
node.prev = newNode;
}
/* add pair into node; existence free room in the node should be checked
* before call
*/
private void appendFromRight(Node<K, V> node, K keyObj, V value) {
if (node.right_idx == Node.NODE_SIZE - 1) {
int left_idx = node.left_idx;
int left_idxMinus1 = left_idx - 1;
System.arraycopy(node.keys, left_idx, node.keys, left_idxMinus1, Node.NODE_SIZE - left_idx);
System.arraycopy(node.values, left_idx, node.values, left_idxMinus1, Node.NODE_SIZE - left_idx);
node.left_idx = left_idxMinus1;
} else {
node.right_idx++;
}
node.size++;
node.keys[node.right_idx] = keyObj;
node.values[node.right_idx] = value;
}
private void attachToRight(Node<K, V> node, Node<K, V> newNode) {
newNode.parent = node;
// - node.right==null - attach here
node.right = newNode;
newNode.prev = node;
Node<K, V> successor = node.next;
newNode.next = successor;
if (successor != null) {
successor.prev = newNode;
}
node.next = newNode;
}
private Node<K, V> createNode(K keyObj, V value) {
Node<K, V> node = new Node<K, V>();
node.keys[0] = keyObj;
node.values[0] = value;
node.left_idx = 0;
node.right_idx = 0;
node.size = 1;
return node;
}
void balance(Node<K, V> x) {
Node<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;
}
private void rightRotate(Node<K, V> x) {
Node<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;
}
private void leftRotate(Node<K, V> x) {
Node<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;
}
/**
* 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.
*/
@Override
public void putAll(Map<? extends K, ? extends V> map) {
super.putAll(map);
}
/**
* 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.
*/
@Override
public V remove(Object key) {
if (size == 0) {
return null;
}
Comparable<K> object = comparator == null ? toComparable((K) key) : null;
K keyK = (K) key;
Node<K, V> node = root;
while (node != null) {
K[] keys = node.keys;
int left_idx = node.left_idx;
int result = cmp(object, keyK, keys[left_idx]);
if (result < 0) {
node = node.left;
} else if (result == 0) {
V value = node.values[left_idx];
removeLeftmost(node);
return value;
} else {
int right_idx = node.right_idx;
if (left_idx != right_idx) {
result = cmp(object, keyK, keys[right_idx]);
}
if (result > 0) {
node = node.right;
} else if (result == 0) {
V value = node.values[right_idx];
removeRightmost(node);
return value;
} else { /*search in node*/
int low = left_idx + 1, mid = 0, high = right_idx - 1;
while (low <= high) {
mid = (low + high) >>> 1;
result = cmp(object, keyK, keys[mid]);
if (result > 0) {
low = mid + 1;
} else if (result == 0) {
V value = node.values[mid];
removeMiddleElement(node, mid);
return value;
} else {
high = mid - 1;
}
}
return null;
}
}
}
return null;
}
void removeLeftmost(Node<K, V> node) {
int index = node.left_idx;
if (node.size == 1) {
deleteNode(node);
} else if (node.prev != null && (Node.NODE_SIZE - 1 - node.prev.right_idx) > node.size) {
// move all to prev node and kill it
Node<K, V> prev = node.prev;
int size = node.right_idx - index;
System.arraycopy(node.keys, index + 1, prev.keys, prev.right_idx + 1, size);
System.arraycopy(node.values, index + 1, prev.values, prev.right_idx + 1, size);
prev.right_idx += size;
prev.size += size;
deleteNode(node);
} else if (node.next != null && (node.next.left_idx) > node.size) {
// move all to next node and kill it
Node<K, V> next = node.next;
int size = node.right_idx - index;
int next_new_left = next.left_idx - size;
next.left_idx = next_new_left;
System.arraycopy(node.keys, index + 1, next.keys, next_new_left, size);
System.arraycopy(node.values, index + 1, next.values, next_new_left, size);
next.size += size;
deleteNode(node);
} else {
node.keys[index] = null;
node.values[index] = null;
node.left_idx++;
node.size--;
Node<K, V> prev = node.prev;
if (prev != null && prev.size == 1) {
node.size++;
node.left_idx--;
node.keys [node.left_idx] = prev.keys [prev.left_idx];
node.values[node.left_idx] = prev.values[prev.left_idx];
deleteNode(prev);
}
}
modCount++;
size--;
}
void removeRightmost(Node<K, V> node) {
int index = node.right_idx;
if (node.size == 1) {
deleteNode(node);
} else if (node.prev != null && (Node.NODE_SIZE - 1 - node.prev.right_idx) > node.size) {
// move all to prev node and kill it
Node<K, V> prev = node.prev;
int left_idx = node.left_idx;
int size = index - left_idx;
System.arraycopy(node.keys, left_idx, prev.keys, prev.right_idx + 1, size);
System.arraycopy(node.values, left_idx, prev.values, prev.right_idx + 1, size);
prev.right_idx += size;
prev.size += size;
deleteNode(node);
} else if (node.next != null && (node.next.left_idx) > node.size) {
// move all to next node and kill it
Node<K, V> next = node.next;
int left_idx = node.left_idx;
int size = index - left_idx;
int next_new_left = next.left_idx - size;
next.left_idx = next_new_left;
System.arraycopy(node.keys, left_idx, next.keys, next_new_left, size);
System.arraycopy(node.values, left_idx, next.values, next_new_left, size);
next.size += size;
deleteNode(node);
} else {
node.keys[index] = null;
node.values[index] = null;
node.right_idx--;
node.size--;
Node<K, V> next = node.next;
if (next != null && next.size == 1) {
node.size++;
node.right_idx++;
node.keys[node.right_idx] = next.keys[next.left_idx];
node.values[node.right_idx] = next.values[next.left_idx];
deleteNode(next);
}
}
modCount++;
size--;
}
void removeMiddleElement(Node<K, V> node, int index) {
// this function is called iff index if some middle element;
// so node.left_idx < index < node.right_idx
// condition above assume that node.size > 1
if (node.prev != null && (Node.NODE_SIZE - 1 - node.prev.right_idx) > node.size) {
// move all to prev node and kill it
Node<K, V> prev = node.prev;
int left_idx = node.left_idx;
int size = index - left_idx;
System.arraycopy(node.keys, left_idx, prev.keys, prev.right_idx + 1, size);
System.arraycopy(node.values, left_idx, prev.values, prev.right_idx + 1, size);
prev.right_idx += size;
size = node.right_idx - index;
System.arraycopy(node.keys, index + 1, prev.keys, prev.right_idx + 1, size);
System.arraycopy(node.values, index + 1, prev.values, prev.right_idx + 1, size);
prev.right_idx += size;
prev.size += (node.size - 1);
deleteNode(node);
} else if (node.next != null && (node.next.left_idx) > node.size) {
// move all to next node and kill it
Node<K, V> next = node.next;
int left_idx = node.left_idx;
int next_new_left = next.left_idx - node.size + 1;
next.left_idx = next_new_left;
int size = index - left_idx;
System.arraycopy(node.keys, left_idx, next.keys, next_new_left, size);
System.arraycopy(node.values, left_idx, next.values, next_new_left, size);
next_new_left += size;
size = node.right_idx - index;
System.arraycopy(node.keys, index + 1, next.keys, next_new_left, size);
System.arraycopy(node.values, index + 1, next.values, next_new_left, size);
next.size += (node.size - 1);
deleteNode(node);
} else {
int moveFromRight = node.right_idx - index;
int left_idx = node.left_idx;
int moveFromLeft = index - left_idx ;
if (moveFromRight <= moveFromLeft) {
System.arraycopy(node.keys, index + 1, node.keys, index, moveFromRight);
System.arraycopy(node.values, index + 1, node.values, index, moveFromRight);
Node<K, V> next = node.next;
if (next != null && next.size == 1) {
node.keys [node.right_idx] = next.keys [next.left_idx];
node.values[node.right_idx] = next.values[next.left_idx];
deleteNode(next);
} else {
node.keys [node.right_idx] = null;
node.values[node.right_idx] = null;
node.right_idx--;
node.size--;
}
} else {
System.arraycopy(node.keys, left_idx , node.keys, left_idx + 1, moveFromLeft);
System.arraycopy(node.values, left_idx , node.values, left_idx + 1, moveFromLeft);
Node<K, V> prev = node.prev;
if (prev != null && prev.size == 1) {
node.keys [left_idx ] = prev.keys [prev.left_idx];
node.values[left_idx ] = prev.values[prev.left_idx];
deleteNode(prev);
} else {
node.keys [left_idx ] = null;
node.values[left_idx ] = null;
node.left_idx++;
node.size--;
}
}
}
modCount++;
size--;
}
void removeFromIterator(Node<K, V> node, int index) {
if (node.size == 1) {
// it is safe to delete the whole node here.
// iterator already moved to the next node;
deleteNode(node);
} else {
int left_idx = node.left_idx;
if (index == left_idx) {
Node<K, V> prev = node.prev;
if (prev != null && prev.size == 1) {
node.keys [left_idx] = prev.keys [prev.left_idx];
node.values[left_idx] = prev.values[prev.left_idx];
deleteNode(prev);
} else {
node.keys [left_idx] = null;
node.values[left_idx] = null;
node.left_idx++;
node.size--;
}
} else if (index == node.right_idx) {
node.keys [index] = null;
node.values[index] = null;
node.right_idx--;
node.size--;
} else {
int moveFromRight = node.right_idx - index;
int moveFromLeft = index - left_idx;
if (moveFromRight <= moveFromLeft) {
System.arraycopy(node.keys, index + 1, node.keys, index, moveFromRight );
System.arraycopy(node.values, index + 1, node.values, index, moveFromRight );
node.keys [node.right_idx] = null;
node.values[node.right_idx] = null;
node.right_idx--;
node.size--;
} else {
System.arraycopy(node.keys, left_idx, node.keys, left_idx+ 1, moveFromLeft);
System.arraycopy(node.values, left_idx, node.values, left_idx+ 1, moveFromLeft);
node.keys [left_idx] = null;
node.values[left_idx] = null;
node.left_idx++;
node.size--;
}
}
}
modCount++;
size--;
}
private void deleteNode(Node<K, V> node) {
if (node.right == null) {
if (node.left != null) {
attachToParent(node, node.left);
} else {
attachNullToParent(node);
}
fixNextChain(node);
} else if(node.left == null) { // node.right != null
attachToParent(node, node.right);
fixNextChain(node);
} else {
// Here node.left!=nul && node.right!=null
// node.next should replace node in tree
// node.next!=null by tree logic.
// node.next.left==null by tree logic.
// node.next.right may be null or non-null
Node<K, V> toMoveUp = node.next;
fixNextChain(node);
if(toMoveUp.right==null){
attachNullToParent(toMoveUp);
} else {
attachToParent(toMoveUp, toMoveUp.right);
}
// Here toMoveUp is ready to replace node
toMoveUp.left = node.left;
if (node.left != null) {
node.left.parent = toMoveUp;
}
toMoveUp.right = node.right;
if (node.right != null) {
node.right.parent = toMoveUp;
}
attachToParentNoFixup(node,toMoveUp);
toMoveUp.color = node.color;
}
}
private void attachToParentNoFixup(Node<K, V> toDelete, Node<K, V> toConnect) {
// assert toConnect!=null
Node<K,V> parent = toDelete.parent;
toConnect.parent = parent;
if (parent == null) {
root = toConnect;
} else if (toDelete == parent.left) {
parent.left = toConnect;
} else {
parent.right = toConnect;
}
}
private void attachToParent(Node<K, V> toDelete, Node<K, V> toConnect) {
// assert toConnect!=null
attachToParentNoFixup(toDelete,toConnect);
if (!toDelete.color) {
fixup(toConnect);
}
}
private void attachNullToParent(Node<K, V> toDelete) {
Node<K, V> parent = toDelete.parent;
if (parent == null) {
root = null;
} else {
if (toDelete == parent.left) {
parent.left = null;
} else {
parent.right = null;
}
if (!toDelete.color) {
fixup(parent);
}
}
}
private void fixNextChain(Node<K, V> node) {
if (node.prev != null) {
node.prev.next = node.next;
}
if (node.next != null) {
node.next.prev = node.prev;
}
}
private void fixup(Node<K, V> x) {
Node<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 number of mappings in this map.
*
* @return the number of mappings in this map.
*/
@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.
*
* @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.
*/
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();
}
/**
* 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.
*
* @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.
*/
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>
* 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.
*
* @return a collection of the values contained in this map.
*/
@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) {
Node<K, V> node = minimum(root);
while (node != null) {
int to = node.right_idx;
for (int i = node.left_idx; i <= to; i++) {
stream.writeObject(node.keys[i]);
stream.writeObject(node.values[i]);
}
node = node.next;
}
}
}
@SuppressWarnings("unchecked")
private void readObject(ObjectInputStream stream) throws IOException,
ClassNotFoundException {
stream.defaultReadObject();
int size = stream.readInt();
Node<K, V> lastNode = null;
for (int i = 0; i < size; i++) {
lastNode = addToLast(lastNode, (K) stream.readObject(), (V) stream.readObject());
}
}
}