Index: modules/luni/src/main/java/java/util/TreeMap.java =================================================================== --- modules/luni/src/main/java/java/util/TreeMap.java (revision 600084) +++ modules/luni/src/main/java/java/util/TreeMap.java (working copy) @@ -27,85 +27,117 @@ * supported, adding and removing. 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 extends AbstractMap implements SortedMap, Cloneable, - Serializable { - private static final long serialVersionUID = 919286545866124006L; +public class TreeMap extends AbstractMap implements SortedMap, + Cloneable, Serializable { + private static final long serialVersionUID = 919286545866124006L; - transient int size; + transient int size; - transient Entry root; - private Comparator comparator; transient int modCount; transient Set> entrySet; - static final int SMALL_LIMIT=127; - transient K[] small_keys; - transient V[] small_values; - transient Entry[] small_entries; - transient int small_left=0; - transient int small_right=-1; + transient Node root; - /** - * Entry is an internal class which is used to hold the entries of a - * TreeMap. - */ - static class Entry extends MapEntry { - Entry parent, left, right; + static class Node implements Cloneable { + static final int NODE_SIZE = 64; + Node prev, next; + Node parent, left, right; + V[] values; + K[] keys; + int left_idx = 0; + int right_idx = -1; + int size = 0; + boolean color; - boolean color; + public Node() { + keys = (K[]) new Object[NODE_SIZE]; + values = (V[]) new Object[NODE_SIZE]; + } - Entry(K key) { - super(key); - } - - Entry(K key, V value) { - super(key, value); - } - - @SuppressWarnings("unchecked") - Entry clone(Entry parent) { - Entry clone = (Entry) super.clone(); - clone.parent = parent; - if (left != null) { + @SuppressWarnings("unchecked") + Node clone(Node parent) throws CloneNotSupportedException { + Node clone = (Node) 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) { + if (right != null) { clone.right = right.clone(clone); } - return clone; - } - } + clone.prev = null; + clone.next = null; + return clone; + } + } @SuppressWarnings("unchecked") - private static Comparable toComparable(T obj) { - return (Comparable)obj; + private static Comparable toComparable(T obj) { + return (Comparable) obj; } - private static class AbstractMapIterator { + static class AbstractMapIterator { TreeMap backingMap; int expectedModCount; - TreeMap.Entry node; - TreeMap.Entry lastNode; + Node node; + Node lastNode; + int offset; + int lastOffset; - AbstractMapIterator(TreeMap map, Entry startNode) { + AbstractMapIterator(TreeMap map, Node startNode, int startOffset) { backingMap = map; expectedModCount = map.modCount; node = startNode; + offset = startOffset; } + AbstractMapIterator(TreeMap map, Node startNode) { + this(map, startNode, startNode != null ? + startNode.right_idx - startNode.left_idx : 0); + } + + AbstractMapIterator(TreeMap 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) { - backingMap.rbDelete(lastNode); + int idx = lastNode.right_idx - lastOffset; + backingMap.remove(lastNode, idx); lastNode = null; expectedModCount++; } else { @@ -117,957 +149,970 @@ } } - private static class UnboundedIterator extends AbstractMapIterator { + static class UnboundedEntryIterator extends AbstractMapIterator + implements Iterator> { - public UnboundedIterator(TreeMap treeMap, Entry entry) { - super(treeMap, entry); - } - - final void makeNext() { - if (expectedModCount != backingMap.modCount) { - throw new ConcurrentModificationException(); - } else if (node == null) { - throw new NoSuchElementException(); - } - lastNode = node; - node = TreeMap.successor(node); - } - - } - - private static class UnboundedEntryIterator extends UnboundedIterator implements Iterator> { - - UnboundedEntryIterator(TreeMap map, Entry startNode) { - super(map, startNode); - } - - UnboundedEntryIterator(TreeMap map) { - super(map, map.root == null ? null : TreeMap.minimum(map.root)); - } - - public Map.Entry next() { - makeNext(); - return lastNode; - } + UnboundedEntryIterator(TreeMap map, Node startNode, int startOffset) { + super(map, startNode, startOffset); } - static class UnboundedKeyIterator extends UnboundedIterator implements Iterator { - public UnboundedKeyIterator(TreeMap treeMap, Entry entry) { - super(treeMap, entry); - } - - public UnboundedKeyIterator(TreeMap map) { - super(map, map.root == null ? null : TreeMap.minimum(map.root)); - } - - public K next() { - makeNext(); - return lastNode.key; - } + UnboundedEntryIterator(TreeMap map) { + super(map); } - static class UnboundedValueIterator extends UnboundedIterator implements Iterator { - - public UnboundedValueIterator(TreeMap treeMap, Entry startNode) { - super(treeMap, startNode); - } - - public UnboundedValueIterator(TreeMap map) { - super(map, map.root == null ? null : TreeMap.minimum(map.root)); - } - - public V next() { - makeNext(); - return lastNode.value; - } + public Map.Entry next() { + makeNext(); + int idx = lastNode.right_idx - lastOffset; + return new MapEntry(lastNode.keys[idx], lastNode.values[idx]); } + } - private static class BoundedIterator extends AbstractMapIterator { - private final TreeMap.Entry finishNode; + static class UnboundedKeyIterator extends AbstractMapIterator + implements Iterator { - BoundedIterator(TreeMap map, Entry startNode, Entry finishNode) { - super(map, startNode); - this.finishNode = finishNode; - } - - final void makeNext() { - if (expectedModCount != backingMap.modCount) { - throw new ConcurrentModificationException(); - } else if (node == null) { - throw new NoSuchElementException(); - } - lastNode = node; - if(node!=finishNode) { - node = TreeMap.successor(node); - } else { - node = null; - } - } + UnboundedKeyIterator(TreeMap map, Node startNode, int startOffset) { + super(map, startNode, startOffset); } - - private static class BoundedEntryIterator extends - BoundedIterator implements Iterator> { - - BoundedEntryIterator(TreeMap map, Entry startNode, Entry finishNode) { - super(map, startNode, finishNode); + UnboundedKeyIterator(TreeMap map) { + super(map); } - public Map.Entry next() { + public K next() { makeNext(); - return lastNode; + return lastNode.keys[lastNode.right_idx - lastOffset]; } } - private static class BoundedKeyIterator extends - BoundedIterator implements Iterator { + static class UnboundedValueIterator extends AbstractMapIterator + implements Iterator { - BoundedKeyIterator(TreeMap map, Entry startNode, Entry finishNode) { - super(map, startNode, finishNode); + UnboundedValueIterator(TreeMap map, Node startNode, int startOffset) { + super(map, startNode, startOffset); } - public K next() { - makeNext(); - return lastNode.key; + UnboundedValueIterator(TreeMap map) { + super(map); } - } - private static class BoundedValueIterator extends - BoundedIterator implements Iterator { - - BoundedValueIterator(TreeMap map, Entry startNode, Entry finishNode) { - super(map, startNode, finishNode); - } - public V next() { makeNext(); - return lastNode.value; + return lastNode.values[lastNode.right_idx - lastOffset]; } } - private static class SmallMapIterator { - TreeMap backingMap; - int expectedModCount; - int index; - int lastIndex; - int endIndex; + static class BoundedMapIterator extends AbstractMapIterator { - SmallMapIterator(TreeMap map, int startIndex, int endIndex) { - backingMap = map; - expectedModCount = map.modCount; - index = startIndex; - this.endIndex = endIndex; + Node finalNode; + int finalOffset; + + BoundedMapIterator(Node startNode, int startOffset, TreeMap map, + Node finalNode, int finalOffset) { + super(map, startNode, startOffset); + this.finalNode = finalNode; + this.finalOffset = finalOffset; } - public boolean hasNext() { - return index<=endIndex; + BoundedMapIterator(Node startNode, TreeMap map, + Node finalNode, int finalOffset) { + this(startNode, startNode != null ? + startNode.right_idx - startNode.left_idx : 0, + map, finalNode, finalOffset); } - final void makeNext() { - if (expectedModCount != backingMap.modCount) { - throw new ConcurrentModificationException(); - } else if (index>endIndex) { - throw new NoSuchElementException(); - } - lastIndex = index++; - } + BoundedMapIterator(Node startNode, int startOffset, + TreeMap map, Node finalNode) { + this(startNode, startOffset, map, finalNode, + finalNode.right_idx - finalNode.left_idx); + } - final public void remove() { - if (expectedModCount == backingMap.modCount) { - if (lastIndex != -1) { - if(backingMap.smallDelete(lastIndex)) { - endIndex--; - index--; - } - lastIndex = -1; - expectedModCount++; - } else { - throw new IllegalStateException(); - } - } else { - throw new ConcurrentModificationException(); + void makeBoundedNext() { + boolean endOfIterator = node == finalNode && offset == finalOffset; + makeNext(); + if (endOfIterator) { + node = null; } } } - private static class SmallEntryIterator extends - SmallMapIterator implements Iterator> { + static class BoundedEntryIterator extends BoundedMapIterator + implements Iterator> { - SmallEntryIterator(TreeMap map, int startIndex, int endIndex) { - super(map, startIndex, endIndex); - } + public BoundedEntryIterator(Node startNode, int startOffset, TreeMap map, + Node finalNode, int finalOffset) { + super(startNode, startOffset, map, finalNode, finalOffset); + } - public Map.Entry next() { - makeNext(); - if(backingMap.small_entries==null) { - backingMap.small_entries = (Entry[])new Entry[backingMap.small_keys.length]; - } - if(backingMap.small_entries[lastIndex]==null) { - backingMap.small_entries[lastIndex]=new Entry(backingMap.small_keys[lastIndex],backingMap.small_values[lastIndex]); - } - return backingMap.small_entries[lastIndex]; - } - } + public Map.Entry next() { + makeBoundedNext(); + int idx = lastNode.right_idx - lastOffset; + return new MapEntry(lastNode.keys[idx], lastNode.values[idx]); + } + } - private static class SmallKeyIterator extends - SmallMapIterator implements Iterator { + static class BoundedKeyIterator extends BoundedMapIterator + implements Iterator { - SmallKeyIterator(TreeMap map, int startIndex, int endIndex) { - super(map, startIndex, endIndex); + public BoundedKeyIterator(Node startNode, int startOffset, TreeMap map, + Node finalNode, int finalOffset) { + super(startNode, startOffset, map, finalNode, finalOffset); } public K next() { - makeNext(); - return backingMap.small_keys[lastIndex]; + makeBoundedNext(); + return lastNode.keys[lastNode.right_idx - lastOffset]; } } - private static class SmallValueIterator extends - SmallMapIterator implements Iterator { + static class BoundedValueIterator extends BoundedMapIterator + implements Iterator { - SmallValueIterator(TreeMap map, int startIndex, int endIndex) { - super(map, startIndex, endIndex); + public BoundedValueIterator(Node startNode, int startOffset, TreeMap map, + Node finalNode, int finalOffset) { + super(startNode, startOffset, map, finalNode, finalOffset); } public V next() { - makeNext(); - return backingMap.small_values[lastIndex]; + makeBoundedNext(); + return lastNode.values[lastNode.right_idx - lastOffset]; } } - static final class SubMap extends AbstractMap implements SortedMap, Serializable { - private static final long serialVersionUID = -6520786458950516097L; + static final class SubMap extends AbstractMap + implements SortedMap, Serializable { + private static final long serialVersionUID = -6520786458950516097L; - private TreeMap backingMap; + private TreeMap backingMap; - boolean hasStart, hasEnd; + boolean hasStart, hasEnd; + K startKey, endKey; + transient Set> entrySet = null; + transient int firstKeyModCount = -1; + transient int lastKeyModCount = -1; + transient Node firstKeyNode; + transient int firstKeyIndex; + transient Node lastKeyNode; + transient int lastKeyIndex; - K startKey, endKey; + SubMap(K start, TreeMap map) { + backingMap = map; + hasStart = true; + startKey = start; + } - transient Set> entrySet = null; - transient int firstEntryModCount = -1; - transient int lastEntryModCount = -1; - transient TreeMap.Entry firstEntry; - transient TreeMap.Entry lastEntry; + SubMap(K start, TreeMap map, K end) { + backingMap = map; + hasStart = hasEnd = true; + startKey = start; + endKey = end; + } - SubMap(K start, TreeMap map) { - backingMap = map; - hasStart = true; - startKey = start; - } + SubMap(TreeMap map, K end) { + backingMap = map; + hasEnd = true; + endKey = end; + } - SubMap(K start, TreeMap map, K end) { - backingMap = map; - hasStart = hasEnd = true; - startKey = start; - endKey = end; + private void checkRange(K key) { + Comparator cmp = backingMap.comparator; + if (cmp == null) { + Comparable 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(); + } } + } - SubMap(TreeMap map, K end) { - backingMap = map; - hasEnd = true; - endKey = end; + private boolean isInRange(K key) { + Comparator cmp = backingMap.comparator; + if (cmp == null) { + Comparable 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 void checkRange(K key) { + private boolean checkUpperBound(K key) { + if (hasEnd) { Comparator cmp = backingMap.comparator; if (cmp == null) { - Comparable 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(); - } + return (toComparable(key).compareTo(endKey) < 0); } + return (cmp.compare(key, endKey) < 0); } + return true; + } - private boolean isInRange(K key) { + private boolean checkLowerBound(K key) { + if (hasStart) { Comparator cmp = backingMap.comparator; if (cmp == null) { - Comparable 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 (toComparable(key).compareTo(startKey) >= 0); } - return true; + return (cmp.compare(key, startKey) >= 0); } + return true; + } - private boolean checkUpperBound(K key) { - if (hasEnd) { - Comparator cmp = backingMap.comparator; - if (cmp == null) { - return (toComparable(key).compareTo(endKey) < 0); - } - return (cmp.compare(key, endKey) < 0); - } - return true; + public Comparator comparator() { + return backingMap.comparator(); + } + + @SuppressWarnings("unchecked") + @Override + public boolean containsKey(Object key) { + if (isInRange((K) key)) { + return backingMap.containsKey(key); } + return false; + } - private boolean checkLowerBound(K key) { - if (hasStart) { - Comparator cmp = backingMap.comparator; - if (cmp == null) { - return (toComparable(key).compareTo(startKey) >= 0); + @Override + public void clear() { + keySet().clear(); + } + + @Override + public boolean containsValue(Object value) { + Iterator it = values().iterator(); + if (value != null) { + while (it.hasNext()) { + if (value.equals(it.next())) { + return true; } - return (cmp.compare(key, startKey) >= 0); } - return true; + } else { + while (it.hasNext()) { + if (it.next() == null) { + return true; + } + } } + return false; + } - public Comparator comparator() { - return backingMap.comparator(); + @Override + public Set> entrySet() { + if (entrySet == null) { + entrySet = new SubMapEntrySet(this); } + return entrySet; + } - @SuppressWarnings("unchecked") - @Override - public boolean containsKey(Object key) { - if (isInRange((K)key)) { - return backingMap.containsKey(key); - } - return false; + private void setFirstKey() { + if (firstKeyModCount == backingMap.modCount) { + return; } - - @Override - public Set> entrySet() { - if(entrySet==null) { - entrySet = new SubMapEntrySet(this); - } - return entrySet; - } - - public K firstKey() { - if(backingMap.size>0) { - if(backingMap.isSmall()) { - if(!hasStart) { - K kres = backingMap.small_keys[backingMap.small_left]; - if(checkUpperBound(kres)) { - return kres; + Comparable object = backingMap.comparator == null ? + toComparable((K) startKey) : null; + K key = (K) startKey; + Node node = backingMap.root; + Node 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; } - - } else { - int idx = backingMap.smallFindAfter(startKey); - if(idx>=backingMap.small_left && idx <=backingMap.small_right){ - K kres = backingMap.small_keys[idx]; - if(checkUpperBound(kres)) { - return kres; - } - } } - } else { - TreeMap.Entry node = firstEntry(); - if (node != null ) { - return node.key; - } + break TOP_LOOP; } } - throw new NoSuchElementException(); } + if (foundNode != null && !checkUpperBound(foundNode.keys[foundIndex])) { + foundNode = null; + } + firstKeyNode = foundNode; + firstKeyIndex = foundIndex; + firstKeyModCount = backingMap.modCount; + } - TreeMap.Entry firstEntry() { - if(firstEntryModCount == backingMap.modCount) { - return firstEntry; - } - TreeMap.Entry node; + public K firstKey() { + if (backingMap.size > 0) { if (!hasStart) { - TreeMap.Entry root = backingMap.root; - node = (root == null) ? null : minimum(root); + Node node = minimum(backingMap.root); + if (node != null && checkUpperBound(node.keys[node.left_idx])) { + return node.keys[node.left_idx]; + } } else { - node = backingMap.findAfter(startKey); + setFirstKey(); + if (firstKeyNode != null) { + return firstKeyNode.keys[firstKeyIndex]; + } } - if (node != null && !checkUpperBound(node.key)) { - node = null; - } - firstEntry = node; - firstEntryModCount = backingMap.modCount; - return node; } + throw new NoSuchElementException(); + } - @SuppressWarnings("unchecked") - @Override - public V get(Object key) { - if (isInRange((K)key)) { - return backingMap.get(key); - } - return null; + + @SuppressWarnings("unchecked") + @Override + public V get(Object key) { + if (isInRange((K) key)) { + return backingMap.get(key); } + return null; + } - public SortedMap headMap(K endKey) { - checkRange(endKey); - if (hasStart) { - return new SubMap(startKey, backingMap, endKey); - } - return new SubMap(backingMap, endKey); + public SortedMap headMap(K endKey) { + checkRange(endKey); + if (hasStart) { + return new SubMap(startKey, backingMap, endKey); } + return new SubMap(backingMap, endKey); + } - @Override - public boolean isEmpty() { - if (!hasStart) { - return firstEntry()==null; - } else { - return lastEntry()==null; - } + @Override + public boolean isEmpty() { + if (hasStart) { + setFirstKey(); + return firstKeyNode == null; + } else { + setLastKey(); + return lastKeyNode == null; } + } - @Override - public Set keySet() { - if (keySet == null) { - keySet = new SubMapKeySet(this); - } - return keySet; + @Override + public Set keySet() { + if (keySet == null) { + keySet = new SubMapKeySet(this); } + return keySet; + } - public K lastKey() { - if (backingMap.size > 0) { - if (backingMap.isSmall()) { - if (!hasEnd) { - K kres = backingMap.small_keys[backingMap.small_right]; - if(checkLowerBound(kres)) { - return kres; + private void setLastKey() { + if (lastKeyModCount == backingMap.modCount) { + return; + } + Comparable object = backingMap.comparator == null ? + toComparable((K) endKey) : null; + K key = (K) endKey; + Node node = backingMap.root; + Node 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 { - int idx = backingMap.smallFindBefore(endKey); - if (idx>=backingMap.small_left && idx <= backingMap.small_right) { - K kres = backingMap.small_keys[idx] ; - if(checkLowerBound(kres)) { - return kres; - } + 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; } } - } else { - TreeMap.Entry node = lastEntry(); - if (node != null) { - return node.key; - } + break TOP_LOOP; } } - throw new NoSuchElementException(); } + if (foundNode != null && !checkLowerBound(foundNode.keys[foundIndex])) { + foundNode = null; + } + lastKeyNode = foundNode; + lastKeyIndex = foundIndex; + lastKeyModCount = backingMap.modCount; + } - TreeMap.Entry lastEntry() { - if(lastEntryModCount == backingMap.modCount) { - return lastEntry; - } - TreeMap.Entry node; + public K lastKey() { + if (backingMap.size > 0) { if (!hasEnd) { - TreeMap.Entry root = backingMap.root; - node = (root == null) ? null : maximum(root); + Node node = maximum(backingMap.root); + if (node != null && checkLowerBound(node.keys[node.right_idx])) { + return node.keys[node.right_idx]; + } } else { - node = backingMap.findBefore(endKey); + setLastKey(); + if (lastKeyNode != null) { + return lastKeyNode.keys[lastKeyIndex]; + } } - if (node != null && !checkLowerBound(node.key)) { - node = null; - } - lastEntry = node; - lastEntryModCount = backingMap.modCount; - return node; } + throw new NoSuchElementException(); + } - @Override - public V put(K key, V value) { - if (isInRange(key)) { - return backingMap.put(key, value); - } - throw new IllegalArgumentException(); + + @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; + @SuppressWarnings("unchecked") + @Override + public V remove(Object key) { + if (isInRange((K) key)) { + return backingMap.remove(key); } + return null; + } - public SortedMap subMap(K startKey, K endKey) { - checkRange(startKey); - checkRange(endKey); - Comparator c = backingMap.comparator(); - if (c == null) { - if (toComparable(startKey).compareTo(endKey) <= 0) { - return new SubMap(startKey, backingMap, endKey); - } - } else { - if (c.compare(startKey, endKey) <= 0) { - return new SubMap(startKey, backingMap, endKey); - } + public SortedMap subMap(K startKey, K endKey) { + checkRange(startKey); + checkRange(endKey); + Comparator c = backingMap.comparator(); + if (c == null) { + if (toComparable(startKey).compareTo(endKey) <= 0) { + return new SubMap(startKey, backingMap, endKey); } - throw new IllegalArgumentException(); + } else { + if (c.compare(startKey, endKey) <= 0) { + return new SubMap(startKey, backingMap, endKey); + } } + throw new IllegalArgumentException(); + } - public SortedMap tailMap(K startKey) { - checkRange(startKey); - if (hasEnd) { - return new SubMap(startKey, backingMap, endKey); - } - return new SubMap(startKey, backingMap); + public SortedMap tailMap(K startKey) { + checkRange(startKey); + if (hasEnd) { + return new SubMap(startKey, backingMap, endKey); } + return new SubMap(startKey, backingMap); + } - @Override - public Collection values() { - if(valuesCollection==null) { - valuesCollection = new SubMapValuesCollection(this); - } - return valuesCollection; + @Override + public Collection values() { + if (valuesCollection == null) { + valuesCollection = new SubMapValuesCollection(this); } + return valuesCollection; + } - public int size() { - if(backingMap.isSmall()) { - int start,end; - if (!hasStart) { - start = backingMap.small_left; - } else { - start = backingMap.smallFindAfter(startKey); - } - System.out.println(start); - if (!hasEnd) { - end = backingMap.small_right; - } else { - end = backingMap.smallFindBefore(endKey); - } - System.out.println(end); - if(backingMap.small_left<=start && end <=backingMap.small_right && end-start>=0) { - return end-start+1; - } else { - return 0; - } - } - TreeMap.Entry entry = firstEntry(); - if(entry!=null) { - int cnt=1; - if(hasEnd) { - TreeMap.Entry last = lastEntry(); - while(entry!=last){ - entry = successor(entry); - cnt++; - } - } else { - while((entry=successor(entry))!=null) cnt++; - } - return cnt; - } + public int size() { + Node 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 extends AbstractSet> implements Set> { - SubMap subMap; + static class SubMapEntrySet extends AbstractSet> + implements Set> { + SubMap subMap; - SubMapEntrySet(SubMap map) { - subMap = map; - } + SubMapEntrySet(SubMap map) { + subMap = map; + } - @Override - public boolean isEmpty() { - return subMap.isEmpty(); + @Override + public boolean isEmpty() { + return subMap.isEmpty(); + } + + public Iterator> iterator() { + Node 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(subMap.backingMap, from, from == null ? 0 : from.right_idx - fromIndex); + } + subMap.setLastKey(); + Node to = subMap.lastKeyNode; + int toIndex = subMap.lastKeyIndex; + return new BoundedEntryIterator(from, from == null ? 0 : from.right_idx - fromIndex, subMap.backingMap, to, to == null ? 0 : to.right_idx - toIndex); + } - @Override - public Iterator> iterator() { - if(subMap.backingMap.isSmall()) { - int start, end; - if(subMap.hasStart) { - start = subMap.backingMap.smallFindAfter(subMap.startKey); - } else { - start = subMap.backingMap.small_left; - } - if(subMap.hasEnd) { - end = subMap.backingMap.smallFindBefore(subMap.endKey); - } else { - end = subMap.backingMap.small_right; - } - return new SmallEntryIterator(subMap.backingMap,start,end); + @Override + public int size() { + return subMap.size(); + } + + @SuppressWarnings("unchecked") + @Override + public boolean contains(Object object) { + if (object instanceof Map.Entry) { + Map.Entry entry = (Map.Entry) object; + K key = entry.getKey(); + if (subMap.isInRange(key)) { + V v1 = subMap.get(key), v2 = entry.getValue(); + return v1 == null ? v2 == null : v1.equals(v2); } - TreeMap.Entry startNode = subMap.firstEntry(); - if (subMap.hasEnd) { - TreeMap.Entry lastNode = subMap.lastEntry(); - return new BoundedEntryIterator(subMap.backingMap, startNode, lastNode); - } - return new UnboundedEntryIterator(subMap.backingMap, startNode); } + return false; + } - @Override - public int size() { - return subMap.size(); + @Override + public boolean remove(Object object) { + if (contains(object)) { + Map.Entry entry = (Map.Entry) object; + K key = entry.getKey(); + subMap.remove(key); + return true; } + return false; + } + } - @SuppressWarnings("unchecked") - @Override - public boolean contains(Object object) { - if (object instanceof Map.Entry) { - Map.Entry entry = (Map.Entry) object; - K key = entry.getKey(); - if (subMap.isInRange(key)) { - V v1 = subMap.get(key), v2 = entry.getValue(); - return v1 == null ? v2 == null : v1.equals(v2); - } - } - return false; - } + static class SubMapKeySet extends AbstractSet implements Set { + SubMap subMap; + SubMapKeySet(SubMap map) { + subMap = map; } - static class SubMapKeySet extends AbstractSet implements Set { - SubMap subMap; + @Override + public boolean contains(Object object) { + return subMap.containsKey(object); + } - SubMapKeySet(SubMap map) { - subMap = map; - } + @Override + public boolean isEmpty() { + return subMap.isEmpty(); + } - @Override - public boolean contains(Object object) { - return subMap.containsKey(object); - } + @Override + public int size() { + return subMap.size(); + } - @Override - public boolean isEmpty() { - return subMap.isEmpty(); + @Override + public boolean remove(Object object) { + if (subMap.containsKey(object)) { + subMap.remove(object); + return true; } + return false; + } - @Override - public int size() { - return subMap.size(); + public Iterator iterator() { + Node 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; } - - @Override - public Iterator iterator() { - if(subMap.backingMap.isSmall()) { - int start, end; - if(subMap.hasStart) { - start = subMap.backingMap.smallFindAfter(subMap.startKey); - } else { - start = subMap.backingMap.small_left; - } - if(subMap.hasEnd) { - end = subMap.backingMap.smallFindBefore(subMap.endKey); - } else { - end = subMap.backingMap.small_right; - } - return new SmallKeyIterator(subMap.backingMap,start,end); - } - TreeMap.Entry startNode = subMap.firstEntry(); - if (subMap.hasEnd) { - TreeMap.Entry lastNode = subMap.lastEntry(); - return new BoundedKeyIterator(subMap.backingMap, startNode, lastNode); - } - return new UnboundedKeyIterator(subMap.backingMap, startNode); + if (!subMap.hasEnd) { + return new UnboundedKeyIterator(subMap.backingMap, from, + from == null ? 0 : from.right_idx - fromIndex); } + subMap.setLastKey(); + Node to = subMap.lastKeyNode; + int toIndex = subMap.lastKeyIndex; + return new BoundedKeyIterator(from, + from == null ? 0 : from.right_idx - fromIndex, subMap.backingMap, to, + to == null ? 0 : to.right_idx - toIndex); } + } - static class SubMapValuesCollection extends AbstractCollection { - SubMap subMap; + static class SubMapValuesCollection extends AbstractCollection { + SubMap subMap; - public SubMapValuesCollection(SubMap subMap) { - this.subMap = subMap; - } + public SubMapValuesCollection(SubMap subMap) { + this.subMap = subMap; + } - @Override - public boolean isEmpty() { - return subMap.isEmpty(); - } + @Override + public boolean isEmpty() { + return subMap.isEmpty(); + } - @Override - public Iterator iterator() { - if(subMap.backingMap.isSmall()) { - int start, end; - if(subMap.hasStart) { - start = subMap.backingMap.smallFindAfter(subMap.startKey); - } else { - start = subMap.backingMap.small_left; - } - if(subMap.hasEnd) { - end = subMap.backingMap.smallFindBefore(subMap.endKey); - } else { - end = subMap.backingMap.small_right; - } - return new SmallValueIterator(subMap.backingMap,start,end); - } - TreeMap.Entry startNode = subMap.firstEntry(); - if (subMap.hasEnd) { - TreeMap.Entry lastNode = subMap.lastEntry(); - return new BoundedValueIterator(subMap.backingMap, startNode, lastNode); - } - return new UnboundedValueIterator(subMap.backingMap, startNode); + @Override + public Iterator iterator() { + Node 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; } - - @Override - public int size() { - return subMap.size(); + if (!subMap.hasEnd) { + return new UnboundedValueIterator(subMap.backingMap, from, + from == null ? 0 : from.right_idx - fromIndex); } + subMap.setLastKey(); + Node to = subMap.lastKeyNode; + int toIndex = subMap.lastKeyIndex; + return new BoundedValueIterator(from, + from == null ? 0 : from.right_idx - fromIndex, subMap.backingMap, to, + to == null ? 0 : to.right_idx - toIndex); } - private void createSmall(){ - small_keys = (K[])new Object[SMALL_LIMIT]; - small_values = (V[])new Object[SMALL_LIMIT]; + @Override + public int size() { + return subMap.size(); + } } - private void clearSmall(){ - small_keys = null; - small_values = null; - small_entries = null; - small_right = -1; - small_left = 0; + /** + * Constructs a new empty instance of spec.TreeMap. + */ + public TreeMap() { } - private boolean isSmall(){ - return small_keys!=null; + /** + * Constructs a new empty instance of spec.TreeMap which uses the specified + * Comparator. + * + * @param comparator the Comparator + */ + public TreeMap(Comparator comparator) { + this.comparator = comparator; } - /** - * Constructs a new empty instance of TreeMap. - * - */ - public TreeMap() { - createSmall(); - } + /** + * Constructs a new instance of spec.TreeMap containing the mappings from the + * specified Map and using the natural ordering. + * + * @param map the mappings to add + * @throws ClassCastException when a key in the Map does not implement the Comparable + * interface, or they keys in the Map cannot be compared + */ + public TreeMap(Map map) { + putAll(map); + } - /** - * Constructs a new empty instance of TreeMap which uses the specified - * Comparator. - * - * @param comparator - * the Comparator - */ - public TreeMap(Comparator comparator) { - this.comparator = comparator; - createSmall(); - } + /** + * Constructs a new instance of spec.TreeMap containing the mappings from the + * specified SortedMap and using the same Comparator. + * + * @param map the mappings to add + */ + public TreeMap(SortedMap map) { + this(map.comparator()); + Node lastNode = null; + Iterator> it = map.entrySet().iterator(); + while (it.hasNext()) { + Map.Entry entry = it.next(); + lastNode = addToLast(lastNode, entry.getKey(), entry.getValue()); + } + } - /** - * Constructs a new instance of TreeMap containing the mappings from the - * specified Map and using the natural ordering. - * - * @param map - * the mappings to add - * - * @exception ClassCastException - * when a key in the Map does not implement the Comparable - * interface, or they keys in the Map cannot be compared - */ - public TreeMap(Map map) { - putAll(map); - } + Node addToLast(Node last, K key, V value) { + if (last == null) { + root = last = createNode(key, value); + size = 1; + } else if (last.size == Node.NODE_SIZE) { + Node newNode = createNode(key, value); + attachToRight(last, newNode); + balance(newNode); + size++; + last = newNode; + } else { + appendFromRight(last, key, value); + size++; + } + return last; + } - /** - * Constructs a new instance of TreeMap containing the mappings from the - * specified SortedMap and using the same Comparator. - * - * @param map - * the mappings to add - */ - public TreeMap(SortedMap map) { - this.comparator = map.comparator(); - Iterator> it = map.entrySet().iterator(); - if (it.hasNext()) { - Map.Entry entry = it.next(); - Entry last = new Entry(entry.getKey(), entry.getValue()); - root = last; - size = 1; - while (it.hasNext()) { - entry = it.next(); - Entry x = new Entry(entry.getKey(), entry.getValue()); - x.parent = last; - last.right = x; - size++; - balance(x); - last = x; - } - } - } - - void balance(Entry x) { - Entry y; - x.color = true; - while (x != root && x.parent.color) { - if (x.parent == x.parent.parent.left) { - y = x.parent.parent.right; - if (y != null && y.color) { - x.parent.color = false; - y.color = false; - x.parent.parent.color = true; - x = x.parent.parent; - } else { - if (x == x.parent.right) { - x = x.parent; - leftRotate(x); - } - x.parent.color = false; - x.parent.parent.color = true; - rightRotate(x.parent.parent); - } - } else { - y = x.parent.parent.left; - if (y != null && y.color) { - x.parent.color = false; - y.color = false; - x.parent.parent.color = true; - x = x.parent.parent; - } else { - if (x == x.parent.left) { - x = x.parent; - rightRotate(x); - } - x.parent.color = false; - x.parent.parent.color = true; - leftRotate(x.parent.parent); - } - } - } - root.color = false; - } - - /** - * Removes all mappings from this TreeMap, leaving it empty. - * - * @see Map#isEmpty - * @see #size - */ - @Override + /** + * Removes all mappings from this spec.TreeMap, leaving it empty. + * + * @see Map#isEmpty + * @see #size + */ + @Override public void clear() { - root = null; - size = 0; - modCount++; - clearSmall(); - createSmall(); - } + root = null; + size = 0; + modCount++; + } - /** - * Answers a new TreeMap with the same mappings, size and comparator as this - * TreeMap. - * - * @return a shallow copy of this TreeMap - * - * @see java.lang.Cloneable - */ - @SuppressWarnings("unchecked") + /** + * Answers a new spec.TreeMap with the same mappings, size and comparator as this + * spec.TreeMap. + * + * @return a shallow copy of this spec.TreeMap + * @see java.lang.Cloneable + */ + @SuppressWarnings("unchecked") @Override public Object clone() { - try { - TreeMap clone = (TreeMap) super.clone(); - clone.entrySet = null; - if (root != null) { + try { + TreeMap clone = (TreeMap) super.clone(); + clone.entrySet = null; + if (root != null) { clone.root = root.clone(null); - } else if(isSmall()) { - clone.createSmall(); - clone.small_entries = null; - System.arraycopy(small_keys,0,clone.small_keys,0,small_keys.length); - System.arraycopy(small_values,0,clone.small_values,0,small_values.length); - clone.small_left = small_left; - clone.small_right = small_right; + // restore prev/next chain + Node node = minimum(clone.root); + while (true) { + Node nxt = successor(node); + if (nxt == null) { + break; + } + nxt.prev = node; + node.next = nxt; + node = nxt; + } } - return clone; - } catch (CloneNotSupportedException e) { - return null; - } - } + return clone; + } catch (CloneNotSupportedException e) { + return null; + } + } - /** - * Answers the Comparator used to compare elements in this TreeMap. - * - * @return a Comparator or null if the natural ordering is used - */ - public Comparator comparator() { - return comparator; - } + static private Node successor(Node x) { + if (x.right != null) { + return minimum(x.right); + } + Node y = x.parent; + while (y != null && x == y.right) { + x = y; + y = y.parent; + } + return y; + } - /** - * Searches this TreeMap for the specified key. - * - * @param key - * the object to search for - * @return true if key is a key of this TreeMap, false - * otherwise - * - * @exception ClassCastException - * when the key cannot be compared with the keys in this - * TreeMap - * @exception NullPointerException - * when the key is null and the comparator cannot handle null - */ + /** + * Answers the Comparator used to compare elements in this spec.TreeMap. + * + * @return a Comparator or null if the natural ordering is used + */ + public Comparator comparator() { + return comparator; + } + + /** + * Searches this spec.TreeMap for the specified key. + * + * @param key the object to search for + * @return true if key is a key of this spec.TreeMap, false + * otherwise + * @throws ClassCastException when the key cannot be compared with the keys in this + * spec.TreeMap + * @throws NullPointerException when the key is null and the comparator cannot handle null + */ @Override public boolean containsKey(Object key) { - return isSmall() ? smallFind(key)>=0 : find(key) != null; - } + Comparable object = comparator == null ? toComparable((K) key) : null; + K keyK = (K) key; + Node 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; + } - /** - * Searches this TreeMap for the specified value. - * - * @param value - * the object to search for - * @return true if value is a value of this TreeMap, false - * otherwise - */ + /** + * Searches this spec.TreeMap for the specified value. + * + * @param value the object to search for + * @return true if value is a value of this spec.TreeMap, false + * otherwise + */ @Override public boolean containsValue(Object value) { - if (root != null) { - return containsValue(root, value); - } else if (size > 0 & isSmall()) { - if (value == null) { - for (int i = small_left; i <= small_right; i++) { - if (small_values[i] == null) { + if (root == null) { + return false; + } + Node 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; } } - } else { - for (int i = small_left; i <= small_right; i++) { - if (value.equals(small_values[i])) { + 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; } - private boolean containsValue(Entry node, Object value) { - if (value == null ? node.value == null : value.equals(node.value)) { - return true; - } - if (node.left != null) { - if (containsValue(node.left, value)) { - return true; - } - } - if (node.right != null) { - if (containsValue(node.right, value)) { - return true; - } - } - return false; - } - - /** - * Answers a Set of the mappings contained in this TreeMap. Each element in - * the set is a Map.Entry. The set is backed by this TreeMap so changes to - * one are reflected by the other. The set does not support adding. - * - * @return a Set of the mappings - */ - @Override + /** + * Answers a Set of the mappings contained in this spec.TreeMap. Each element in + * the set is a Map.Entry. The set is backed by this spec.TreeMap so changes to + * one are reflected by the other. The set does not support adding. + * + * @return a Set of the mappings + */ + @Override public Set> entrySet() { if (entrySet == null) { entrySet = new AbstractSet>() { - @Override + @Override public int size() { return size; } @@ -1082,17 +1127,25 @@ public boolean contains(Object object) { if (object instanceof Map.Entry) { Map.Entry entry = (Map.Entry) object; - Object v1 = get(entry.getKey()), v2 = entry.getValue(); + Object v1 = TreeMap.this.get(entry.getKey()), v2 = entry.getValue(); return v1 == null ? v2 == null : v1.equals(v2); } return false; } @Override + public boolean remove(Object object) { + if (contains(object)) { + Map.Entry entry = (Map.Entry) object; + K key = entry.getKey(); + TreeMap.this.remove(key); + return true; + } + return false; + } + + @Override public Iterator> iterator() { - if(isSmall()) { - return new SmallEntryIterator(TreeMap.this,TreeMap.this.small_left,TreeMap.this.small_right); - } return new UnboundedEntryIterator(TreeMap.this); } }; @@ -1100,845 +1153,952 @@ return entrySet; } - /** @return the non-negative index of the element, or a negative index which - * is the -index - 1 where the element would be inserted - */ - private int smallFind(Object keyObj) { - if (small_left > small_right) { - return -1; + /** + * Answers the first sorted key in this spec.TreeMap. + * + * @return the first sorted key + * @throws NoSuchElementException when this spec.TreeMap is empty + */ + public K firstKey() { + if (root != null) { + Node node = minimum(root); + return node.keys[node.left_idx]; } - K key = (K) keyObj; - if (comparator == null) { - Comparable object = toComparable(key); - int low = small_left, mid = 0, high = small_right, result = 0; - while (low <= high) { - mid = (low + high) >> 1; - if ((result = object.compareTo(small_keys[mid])) > 0) { - low = mid + 1; - } else if (result == 0) { - return mid; - } else { - high = mid - 1; + throw new NoSuchElementException(); + } + + + /** + * Answers 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 when the key cannot be compared with the keys in this + * spec.TreeMap + * @throws NullPointerException when the key is null and the comparator cannot handle null + */ + @Override + public V get(Object key) { + Comparable object = comparator == null ? toComparable((K) key) : null; + K keyK = (K) key; + Node 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]); } - } - return -mid - (result <= 0 ? 1 : 2); - } else { - int low = small_left, mid = 0, high = small_right, result = 0; - while (low <= high) { - mid = (low + high) >> 1; - if ((result = comparator.compare(key, small_keys[mid])) > 0) { - low = mid + 1; + if (result > 0) { + node = node.right; } else if (result == 0) { - return mid; - } else { - high = mid - 1; + 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 -mid - (result <= 0 ? 1 : 2); } + return null; } - @SuppressWarnings("unchecked") - private Entry find(Object keyObj) { - int result; - K key = (K)keyObj; - Comparable object = null; - if (comparator == null) { - object = toComparable(key); - Entry x = root; - while (x != null) { - result = object.compareTo(x.key); - if (result == 0) { - return x; - } - x = result < 0 ? x.left : x.right; - } - } else { - Entry x = root; - while (x != null) { - result = comparator.compare(key, x.key); - if (result == 0) { - return x; - } - x = result < 0 ? x.left : x.right; - } - } - return null; - } - - int smallFindAfter(Object keyObj) { - int idx = smallFind(keyObj); - if(idx>=0) { - return idx; - } else { - idx = -idx - 1; - return (idx>small_right) ? -1 : idx; - } + private int cmp(Comparable object, K key1, K key2) { + return object != null ? + object.compareTo(key2) : comparator.compare(key1, key2); } - int smallFindBefore(Object keyObj) { - int idx = smallFind(keyObj); - if(idx>=0) { - return (idx==small_left) ? -1 : idx-1; - } else { - idx = -idx - 1; - return (idx<=small_left) ? -1 : idx-1; - } - } - - @SuppressWarnings("unchecked") - Entry findAfter(Object keyObj) { - K key = (K)keyObj; - int result; - Comparable object = null; - if (comparator == null) { - object = toComparable(key); - } - Entry x = root, last = null; - while (x != null) { - result = object != null ? object.compareTo(x.key) : comparator - .compare(key, x.key); - if (result == 0) { - return x; - } - if (result < 0) { - last = x; - x = x.left; - } else { - x = x.right; - } - } - return last; - } - - Entry findBefore(K key) { - int result; - Comparable object = null; - if (comparator == null) { - object = toComparable(key); - } - Entry x = root, last = null; - while (x != null) { - result = object != null ? object.compareTo(x.key) : comparator - .compare(key, x.key); - if (result <= 0) { - x = x.left; - } else { - last = x; - x = x.right; - } - } - return last; - } - - /** - * Answer the first sorted key in this TreeMap. - * - * @return the first sorted key - * - * @exception NoSuchElementException - * when this TreeMap is empty - */ - public K firstKey() { - if (root != null) { - return minimum(root).key; - } else if(size>0 & isSmall()) { - return small_keys[small_left]; - } - throw new NoSuchElementException(); - } - - private void fixup(Entry x) { - Entry 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; - } - - /** - * Answers the value of the mapping with the specified key. - * - * @param key - * the key - * @return the value of the mapping with the specified key - * - * @exception ClassCastException - * when the key cannot be compared with the keys in this - * TreeMap - * @exception NullPointerException - * when the key is null and the comparator cannot handle null - */ - @Override - public V get(Object key) { - if(isSmall()) { - int idx = smallFind(key); - if(idx >= 0) { - return small_values[idx]; - } - } else { - Entry node = find(key); - if (node != null) { - return node.value; - } - } - return null; - } - - /** - * Answers a SortedMap of the specified portion of this TreeMap which - * contains keys less than the end key. The returned SortedMap is backed by - * this TreeMap so changes to one are reflected by the other. - * - * @param endKey - * the end key - * @return a sub-map where the keys are less than endKey - * - * @exception ClassCastException - * when the end key cannot be compared with the keys in this - * TreeMap - * @exception NullPointerException - * when the end key is null and the comparator cannot handle - * null - */ - public SortedMap headMap(K endKey) { - // Check for errors - if (comparator == null) { + /** + * Answers a SortedMap of the specified portion of this spec.TreeMap which + * contains keys less than the end key. The returned SortedMap is backed by + * this spec.TreeMap so changes to one are reflected by the other. + * + * @param endKey the end key + * @return a sub-map where the keys are less than endKey + * @throws ClassCastException when the end key cannot be compared with the keys in this + * spec.TreeMap + * @throws NullPointerException when the end key is null and the comparator cannot handle + * null + */ + public SortedMap headMap(K endKey) { + // Check for errors + if (comparator == null) { toComparable(endKey).compareTo(endKey); } else { comparator.compare(endKey, endKey); } - return new SubMap(this, endKey); - } + return new SubMap(this, endKey); + } - /** - * Answers a Set of the keys contained in this TreeMap. The set is backed by - * this TreeMap so changes to one are reflected by the other. The set does - * not support adding. - * - * @return a Set of the keys - */ - @Override + /** + * Answers a Set of the keys contained in this spec.TreeMap. The set is backed by + * this spec.TreeMap so changes to one are reflected by the other. The set does + * not support adding. + * + * @return a Set of the keys + */ + @Override public Set keySet() { - if (keySet == null) { - keySet = new AbstractSet() { - @Override + if (keySet == null) { + keySet = new AbstractSet() { + @Override public boolean contains(Object object) { - return containsKey(object); - } + return TreeMap.this.containsKey(object); + } - @Override + @Override public int size() { - return size; - } + return TreeMap.this.size; + } - @Override + @Override public void clear() { - TreeMap.this.clear(); - } + TreeMap.this.clear(); + } - @Override - public Iterator iterator() { - if(isSmall()) { - return new SmallKeyIterator(TreeMap.this,TreeMap.this.small_left,TreeMap.this.small_right); + @Override + public boolean remove(Object object) { + if (contains(object)) { + TreeMap.this.remove(object); + return true; } - return new UnboundedKeyIterator (TreeMap.this); - } - }; - } - return keySet; - } + return false; + } - /** - * Answer the last sorted key in this TreeMap. - * - * @return the last sorted key - * - * @exception NoSuchElementException - * when this TreeMap is empty - */ - public K lastKey() { - if (root != null) { - return maximum(root).key; - } else if(size>0 && isSmall()) { - return small_keys[small_right]; + @Override + public Iterator iterator() { + return new UnboundedKeyIterator(TreeMap.this); + } + }; } - throw new NoSuchElementException(); - } + return keySet; + } - private void leftRotate(Entry x) { - Entry y = x.right; - x.right = y.left; - if (y.left != null) { - y.left.parent = x; + /** + * Answer the last sorted key in this spec.TreeMap. + * + * @return the last sorted key + * @throws NoSuchElementException when this spec.TreeMap is empty + */ + public K lastKey() { + if (root != null) { + Node node = maximum(root); + return node.keys[node.right_idx]; } - 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; - } + throw new NoSuchElementException(); + } - static Entry maximum(Entry x) { - while (x.right != null) { - x = x.right; + static Node minimum(Node x) { + if (x == null) { + return null; } - return x; - } - - static Entry minimum(Entry x) { - while (x.left != null) { + while (x.left != null) { x = x.left; } - return x; - } + return x; + } - static Entry predecessor(Entry x) { - if (x.left != null) { - return maximum(x.left); + static Node maximum(Node x) { + if (x == null) { + return null; } - Entry y = x.parent; - while (y != null && x == y.left) { - x = y; - y = y.parent; - } - return y; - } - - private Entry smallDeflate(int from, int to){ - int elem = (from+to)>>1; - Entry entry = small_entries==null? null:small_entries[elem]; - if(entry == null) { - entry= new Entry(small_keys[elem],small_values[elem]); + while (x.right != null) { + x = x.right; } - if(from<=elem-1) { - entry.left = smallDeflate(from,elem-1); - entry.left.parent = entry; - } - if(elem+1<=to) { - entry.right = smallDeflate(elem+1,to); - entry.right.parent = entry; - } - return entry; + 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 null - * if there was no mapping - * - * @exception ClassCastException - * when the key cannot be compared with the keys in this - * TreeMap - * @exception NullPointerException - * when the key is null and the comparator cannot handle null - */ - @Override + /** + * 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 null + * if there was no mapping + * @throws ClassCastException when the key cannot be compared with the keys in this + * spec.TreeMap + * @throws NullPointerException when the key is null and the comparator cannot handle null + */ + @Override public V put(K key, V value) { - if(isSmall()) { - if(small_left>small_right) { - small_left = small_right = 0; - small_keys[0] = key; - small_values[0] = value; - modCount++; - size++; - return null; + if (root == null) { + root = createNode(key, value); + size = 1; + modCount++; + return null; + } + Comparable object = comparator == null ? toComparable((K) key) : null; + K keyK = (K) key; + Node node = root; + Node 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 idx = smallFind(key); - if(idx>=0) { - V res = small_values[idx]; - small_values[idx] = value; - if(small_entries!=null && small_entries[idx]!=null) { - small_entries[idx].value = value; + 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; + } } - return res; + result = low; + break; } - if(size == SMALL_LIMIT) { - root = smallDeflate(small_left,small_right); - clearSmall(); + } + } /* 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 { - int newIdx = -idx - 1; - - if((small_left==0)||((small_right - newIdx) <= (newIdx - small_left) && ((small_right < SMALL_LIMIT-1)))) { - // move right - System.arraycopy(small_keys,newIdx,small_keys,newIdx+1,small_right-newIdx+1); - System.arraycopy(small_values,newIdx,small_values,newIdx+1,small_right-newIdx+1); - if(small_entries!=null) { - System.arraycopy(small_entries,newIdx,small_entries,newIdx+1,small_right-newIdx+1); + appendFromRight(prevNode, key, value); + } + } else { + // create and link + Node 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 previous = node.prev; + Node nextNode = node.next; + boolean removeFromStart; + boolean attachFromLeft = false; + Node 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; } -// for(int i=small_right; i >= newIdx; i--){ -// small_keys[i+1] = small_keys[i]; -// small_values[i+1] = small_values[i]; -// if(small_entries!=null) { -// small_entries[i+1] = small_entries[i]; -// } -// } - small_right++; } else { - System.arraycopy(small_keys,small_left,small_keys,small_left-1,newIdx-small_left); - System.arraycopy(small_values,small_left,small_values,small_left-1,newIdx-small_left); - if(small_entries!=null) { - System.arraycopy(small_entries,small_left,small_entries,small_left-1,newIdx-small_left); + 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; + } } -// for (int i = small_left; i < newIdx; i++) { -// small_keys[i - 1] = small_keys[i]; -// small_values[i - 1] = small_values[i]; -// if (small_entries != null) { -// small_entries[i - 1] = small_entries[i]; -// } -// } - small_left--; - newIdx--; } - small_keys[newIdx] = key; - small_values[newIdx] = value; - if(small_entries!=null) { - small_keys[newIdx] = null; + } + 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); } - size++; - modCount++; - return null; + } else { + Node newNode = createNode(movedKey, movedValue); + if (attachFromLeft) { + attachToLeft(attachHere, newNode); + } else { + attachToRight(attachHere, newNode); + } + balance(newNode); } } } - MapEntry entry = rbInsert(key); - V result = entry.value; - entry.value = value; - return result; - } + return null; + } - /** - * Copies every mapping in the specified Map to this TreeMap. - * - * @param map - * the Map to copy mappings from - * - * @exception ClassCastException - * when a key in the Map cannot be compared with the keys in - * this TreeMap - * @exception NullPointerException - * when a key in the Map is null and the comparator cannot - * handle null - */ - @Override - public void putAll(Map map) { - super.putAll(map); - } + private void appendFromLeft(Node 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; + } - void rbDelete(Entry z) { - Entry y = z.left == null || z.right == null ? z : successor(z); - Entry x = y.left != null ? y.left : y.right; - if (x != null) { - x.parent = y.parent; + private void attachToLeft(Node node, Node newNode) { + newNode.parent = node; + // node.left==null - attach here + node.left = newNode; + Node predecessor = node.prev; + newNode.prev = predecessor; + newNode.next = node; + if (predecessor != null) { + predecessor.next = newNode; } - if (y.parent == null) { - root = x; - } else if (y == y.parent.left) { - y.parent.left = x; + node.prev = newNode; + } + + /* add pair into node; existence free room in the node should be checked + * before call + */ + private void appendFromRight(Node 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 { - y.parent.right = x; + node.right_idx++; } - modCount++; - if (y != z) { - z.key = y.key; - z.value = y.value; - } - if (!y.color && root != null) { - if (x == null) { - fixup(y.parent); - } else { - fixup(x); - } - } - y.left = y.right = y.parent = null; - size--; - } + node.size++; + node.keys[node.right_idx] = keyObj; + node.values[node.right_idx] = value; + } - private Entry rbInsert(K object) { - int result = 0; - Entry y = null; - if (size != 0) { - Comparable key = null; - if (comparator == null) { - key = toComparable(object); - Entry x = root; - while (x != null) { - y = x; - result = key.compareTo(x.key); - if (result == 0) { - return x; + private void attachToRight(Node node, Node newNode) { + newNode.parent = node; + // - node.right==null - attach here + node.right = newNode; + newNode.prev = node; + Node successor = node.next; + newNode.next = successor; + if (successor != null) { + successor.prev = newNode; + } + node.next = newNode; + } + + private Node createNode(K keyObj, V value) { + Node node = new Node(); + node.keys[0] = keyObj; + node.values[0] = value; + node.left_idx = 0; + node.right_idx = 0; + node.size = 1; + return node; + } + + void balance(Node x) { + Node 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 = result < 0 ? x.left : x.right; + x.parent.color = false; + x.parent.parent.color = true; + rightRotate(x.parent.parent); } } else { - Entry x = root; - while (x != null) { - y = x; - result = comparator.compare(object, x.key); - if (result == 0) { - return x; + 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 = result < 0 ? x.left : x.right; + x.parent.color = false; + x.parent.parent.color = true; + leftRotate(x.parent.parent); } } + } + root.color = false; + } + private void rightRotate(Node x) { + Node y = x.left; + x.left = y.right; + if (y.right != null) { + y.right.parent = x; } - size++; - modCount++; - Entry z = new Entry(object); - if (y == null) { - return root = z; + 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; + } } - z.parent = y; - if (result < 0) { - y.left = z; + y.right = x; + x.parent = y; + } + + + private void leftRotate(Node x) { + Node 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 { - y.right = z; + if (x == x.parent.left) { + x.parent.left = y; + } else { + x.parent.right = y; + } } - balance(z); - return z; - } + y.left = x; + x.parent = y; + } - /** - * Removes a mapping with the specified key from this TreeMap. - * - * @param key - * the key of the mapping to remove - * @return the value of the removed mapping or null if key is not a key in - * this TreeMap - * - * @exception ClassCastException - * when the key cannot be compared with the keys in this - * TreeMap - * @exception NullPointerException - * when the key is null and the comparator cannot handle null - */ - @Override + + /** + * Copies every mapping in the specified Map to this spec.TreeMap. + * + * @param map the Map to copy mappings from + * @throws ClassCastException when a key in the Map cannot be compared with the keys in + * this spec.TreeMap + * @throws NullPointerException when a key in the Map is null and the comparator cannot + * handle null + */ + @Override + public void putAll(Map map) { + super.putAll(map); + } + + /** + * Removes a mapping with the specified key from this spec.TreeMap. + * + * @param key the key of the mapping to remove + * @return the value of the removed mapping or null if key is not a key in + * this spec.TreeMap + * @throws ClassCastException when the key cannot be compared with the keys in this + * spec.TreeMap + * @throws NullPointerException when the key is null and the comparator cannot handle null + */ + @Override public V remove(Object key) { - if (size == 0) { - return null; - } - if(isSmall()){ - int idx = smallFind(key); - if(idx<0) { - return null; + if (size == 0) { + return null; + } + Comparable object = comparator == null ? toComparable((K) key) : null; + K keyK = (K) key; + Node 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]; + remove(node, left_idx); + 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]; + remove(node, right_idx); + 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]; + remove(node, mid); + return value; + } else { + high = mid - 1; + } + } + return null; + } } - V result = small_values[idx]; - smallDelete(idx); - return result; - } else { - Entry node = find(key); - if (node == null) { - return null; - } - V result = node.value; - rbDelete(node); - return result; } - } + return null; + } - private boolean smallDelete(int idx) { - size--; - modCount++; - if(idx==small_left) { - small_keys[idx] = null; - small_values[idx] = null; - if(small_entries!=null) { - small_keys[idx] = null; + void remove(Node node, int index) { + 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 prev = node.prev; + int left_idx = node.left_idx; + if (index != 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; } - small_left++; - return false; - } else if(idx==small_right) { - small_right--; - small_keys[idx] = null; - small_values[idx] = null; - if(small_entries!=null) { - small_keys[idx] = null; + int right_idx = node.right_idx; + if (index != right_idx) { + int size = 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 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; + if (index != left_idx) { + 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; + } + int right_idx = node.right_idx; + if (index != right_idx) { + int size = 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 { - - System.arraycopy(small_keys,idx+1,small_keys,idx,small_right-idx); - System.arraycopy(small_values,idx+1,small_values,idx,small_right-idx); - if(small_entries!=null) { - System.arraycopy(small_entries,idx+1,small_entries,idx,small_right-idx); + if (index == node.left_idx) { + node.keys[index] = null; + node.values[index] = null; + node.left_idx++; + } else if (index == node.right_idx) { + node.keys[index] = null; + node.values[index] = null; + node.right_idx--; + } else if (node.right_idx - index <= index - node.left_idx) { + System.arraycopy(node.keys, index + 1, node.keys, index, node.right_idx - index); + System.arraycopy(node.values, index + 1, node.values, index, node.right_idx - index); + node.right_idx--; + } else { + System.arraycopy(node.keys, node.left_idx, node.keys, node.left_idx + 1, index - node.left_idx); + System.arraycopy(node.values, node.left_idx, node.values, node.left_idx + 1, index - node.left_idx); + node.left_idx++; } -// for(int i=idx+1; i<=small_right; i++) { -// small_keys[i-1] = small_keys[i]; -// small_values[i-1] = small_values[i]; -// if(small_entries!=null) { -// small_entries[i-1] = small_entries[i]; -// } -// } - small_right--; + node.size--; + Node next = node.next; + Node prev = node.prev; + if (next != null && node.right_idx < Node.NODE_SIZE - 1 && 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); + } else if (prev != null && node.left_idx > 0 && 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); + } } - return true; + modCount++; + size--; } - private void rightRotate(Entry x) { - Entry y = x.left; - x.left = y.right; - if (y.right != null) { - y.right.parent = x; + private void deleteNode(Node node) { + Node toDelete, toConnect; + if (node.right == null || node.left == null) { + toDelete = node; + } else { + toDelete = node.next; } - y.parent = x.parent; - if (x.parent == null) { - root = y; - } else { - if (x == x.parent.right) { - x.parent.right = y; + if (node.left != null) { + toConnect = node.left; + } else { + toConnect = node.right; + } + if (toConnect != null) { + toConnect.parent = toDelete.parent; + } + if (toDelete.parent == null) { + root = toConnect; + } else if (toDelete == toDelete.parent.left) { + toDelete.parent.left = toConnect; + } else { + toDelete.parent.right = toConnect; + } + if (toDelete != node) { + node.keys = toDelete.keys; + node.values = toDelete.values; + node.size = toDelete.size; + node.left_idx = toDelete.left_idx; + node.right_idx = toDelete.right_idx; + node.next = toDelete.next; + if (node.next != null) { + node.next.prev = node; + } + } else { + if (node.prev != null) { + node.prev.next = node.next; + } + if (node.next != null) { + node.next.prev = node.prev; + } + } + if (!toDelete.color && root != null) { + if (toConnect == null) { + fixup(toDelete.parent); } else { - x.parent.left = y; + fixup(toConnect); } - } - y.right = x; - x.parent = y; - } + } + } - /** - * Answers the number of mappings in this TreeMap. - * - * @return the number of mappings in this TreeMap - */ - @Override + private void fixup(Node x) { + Node 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; + } + + + /** + * Answers the number of mappings in this spec.TreeMap. + * + * @return the number of mappings in this spec.TreeMap + */ + @Override public int size() { - return size; - } + return size; + } - /** - * Answers a SortedMap of the specified portion of this TreeMap which - * contains keys greater or equal to the start key but less than the end - * key. The returned SortedMap is backed by this TreeMap so changes to one - * are reflected by the other. - * - * @param startKey - * the start key - * @param endKey - * the end key - * @return a sub-map where the keys are greater or equal to - * startKey and less than endKey - * - * @exception ClassCastException - * when the start or end key cannot be compared with the keys - * in this TreeMap - * @exception NullPointerException - * when the start or end key is null and the comparator - * cannot handle null - */ - public SortedMap subMap(K startKey, K endKey) { - if (comparator == null) { - if (toComparable(startKey).compareTo(endKey) <= 0) { + /** + * Answers a SortedMap of the specified portion of this spec.TreeMap which + * contains keys greater or equal to the start key but less than the end + * key. The returned SortedMap is backed by this spec.TreeMap so changes to one + * are reflected by the other. + * + * @param startKey the start key + * @param endKey the end key + * @return a sub-map where the keys are greater or equal to + * startKey and less than endKey + * @throws ClassCastException when the start or end key cannot be compared with the keys + * in this spec.TreeMap + * @throws NullPointerException when the start or end key is null and the comparator + * cannot handle null + */ + public SortedMap subMap(K startKey, K endKey) { + if (comparator == null) { + if (toComparable(startKey).compareTo(endKey) <= 0) { return new SubMap(startKey, this, endKey); } - } else { - if (comparator.compare(startKey, endKey) <= 0) { + } else { + if (comparator.compare(startKey, endKey) <= 0) { return new SubMap(startKey, this, endKey); } - } - throw new IllegalArgumentException(); - } - - static Entry successor(Entry x) { - if (x.right != null) { - return minimum(x.right); } - Entry y = x.parent; - while (y != null && x == y.right) { - x = y; - y = y.parent; - } - return y; - } + throw new IllegalArgumentException(); + } - /** - * Answers a SortedMap of the specified portion of this TreeMap which - * contains keys greater or equal to the start key. The returned SortedMap - * is backed by this TreeMap so changes to one are reflected by the other. - * - * @param startKey - * the start key - * @return a sub-map where the keys are greater or equal to - * startKey - * - * @exception ClassCastException - * when the start key cannot be compared with the keys in - * this TreeMap - * @exception NullPointerException - * when the start key is null and the comparator cannot - * handle null - */ - public SortedMap tailMap(K startKey) { - // Check for errors - if (comparator == null) { + /** + * Answers a SortedMap of the specified portion of this spec.TreeMap which + * contains keys greater or equal to the start key. The returned SortedMap + * is backed by this spec.TreeMap so changes to one are reflected by the other. + * + * @param startKey the start key + * @return a sub-map where the keys are greater or equal to + * startKey + * @throws ClassCastException when the start key cannot be compared with the keys in + * this spec.TreeMap + * @throws NullPointerException when the start key is null and the comparator cannot + * handle null + */ + public SortedMap tailMap(K startKey) { + // Check for errors + if (comparator == null) { toComparable(startKey).compareTo(startKey); } else { comparator.compare(startKey, startKey); } - return new SubMap(startKey, this); - } + return new SubMap(startKey, this); + } - /** - * Answers a Collection of the values contained in this TreeMap. The - * collection is backed by this TreeMap so changes to one are reflected by - * the other. The collection does not support adding. - * - * @return a Collection of the values - */ - @Override + /** + * Answers a Collection of the values contained in this spec.TreeMap. The + * collection is backed by this spec.TreeMap so changes to one are reflected by + * the other. The collection does not support adding. + * + * @return a Collection of the values + */ + @Override public Collection values() { - if (valuesCollection == null) { - valuesCollection = new AbstractCollection() { - @Override + if (valuesCollection == null) { + valuesCollection = new AbstractCollection() { + @Override public boolean contains(Object object) { - return containsValue(object); - } + return containsValue(object); + } - @Override + @Override public int size() { - return size; - } + return size; + } - @Override + @Override public void clear() { - TreeMap.this.clear(); - } + TreeMap.this.clear(); + } - @Override + @Override public Iterator iterator() { - if(isSmall()) { - return new SmallValueIterator(TreeMap.this,TreeMap.this.small_left,TreeMap.this.small_right); - } - return new UnboundedValueIterator (TreeMap.this); - } - }; - } - return valuesCollection; - } + return new UnboundedValueIterator(TreeMap.this); + } + }; + } + return valuesCollection; + } - private void writeObject(ObjectOutputStream stream) throws IOException { - stream.defaultWriteObject(); - stream.writeInt(size); - if (size > 0) { - if(isSmall()) { - for(int i=small_left; i<=small_right; i++){ - stream.writeObject(small_keys[i]); - stream.writeObject(small_values[i]); + private void writeObject(ObjectOutputStream stream) throws IOException { + stream.defaultWriteObject(); + stream.writeInt(size); + if (size > 0) { + Node 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]); } - } else { - Entry node = minimum(root); - while (node != null) { - stream.writeObject(node.key); - stream.writeObject(node.value); - node = successor(node); - } + node = node.next; } - } - } + } + } - @SuppressWarnings("unchecked") + @SuppressWarnings("unchecked") private void readObject(ObjectInputStream stream) throws IOException, - ClassNotFoundException { - stream.defaultReadObject(); - size = stream.readInt(); - if(size>0 && size last = null; - for (int i = size; --i >= 0;) { - Entry node = new Entry((K)stream.readObject()); - node.value = (V)stream.readObject(); - if (last == null) { - root = node; - } else { - node.parent = last; - last.right = node; - balance(node); - } - last = node; - } + ClassNotFoundException { + stream.defaultReadObject(); + int size = stream.readInt(); + Node lastNode = null; + for (int i = 0; i < size; i++) { + lastNode = addToLast(lastNode, (K) stream.readObject(), (V) stream.readObject()); } - } + } } Index: modules/luni/src/main/java/java/util/TreeSet.java =================================================================== --- modules/luni/src/main/java/java/util/TreeSet.java (revision 600084) +++ modules/luni/src/main/java/java/util/TreeSet.java (working copy) @@ -387,18 +387,10 @@ .readObject()); int size = stream.readInt(); if (size > 0) { - E key = (E) stream.readObject(); - TreeMap.Entry last = new TreeMap.Entry(key, key); - map.root = last; - map.size = 1; - for (int i = 1; i < size; i++) { - key = (E) stream.readObject(); - TreeMap.Entry x = new TreeMap.Entry(key, key); - x.parent = last; - last.right = x; - map.size++; - map.balance(x); - last = x; + TreeMap.Node lastNode = null; + for(int i=0; i