/* * 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) { throw new AssertionError(e); // android-changed } } @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) { throw new AssertionError(e); // android-changed } } 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()); } } }