Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
java.util.TreeMap Maven / Gradle / Ivy
/*
* 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;
/**
* 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
*
* @param
* type of key
* @param
* type of value
*
* @since 1.2
*/
public class TreeMap extends AbstractMap implements
NavigableMap {
private static final long serialVersionUID = 919286545866124006L;
transient int size;
transient Node root;
Comparator super K> comparator;
transient int modCount;
transient Set> entrySet;
transient NavigableMap descendingMap;
transient NavigableSet navigableKeySet;
static class Node {
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;
@SuppressWarnings("unchecked")
public Node() {
keys = (K[]) new Object[NODE_SIZE];
values = (V[]) new Object[NODE_SIZE];
}
}
/**
* Entry is an internal class which is used to hold the entries of a
* TreeMap.
*
* also used to record key, value, and position
*/
static class Entry extends MapEntry {
Entry parent, left, right;
Node node;
int index;
public void setLocation(Node node, int index, V value, K key) {
this.node = node;
this.index = index;
this.value = value;
this.key = key;
}
boolean color;
Entry(K theKey) {
super(theKey);
}
Entry(K theKey, V theValue) {
super(theKey, theValue);
}
public V setValue(V object) {
V result = value;
value = object;
this.node.values[index] = value;
return result;
}
}
private static abstract class AbstractSubMapIterator {
final NavigableSubMap subMap;
int expectedModCount;
TreeMap.Node node;
TreeMap.Node lastNode;
TreeMap.Entry boundaryPair;
int offset;
int lastOffset;
boolean getToEnd = false;
AbstractSubMapIterator(final NavigableSubMap map) {
subMap = map;
expectedModCount = subMap.m.modCount;
TreeMap.Entry entry = map.findStartNode();
if (entry != null) {
if (map.toEnd && !map.checkUpperBound(entry.key)) {
} else {
node = entry.node;
offset = entry.index;
boundaryPair = getBoundaryNode();
}
}
}
public void remove() {
if (expectedModCount == subMap.m.modCount) {
if (expectedModCount == subMap.m.modCount) {
K key = (node != null) ? node.keys[offset] : null;
if (lastNode != null) {
int idx = lastOffset;
if (idx == lastNode.left_idx){
subMap.m.removeLeftmost(lastNode);
} else if (idx == lastNode.right_idx) {
subMap.m.removeRightmost(lastNode);
} else {
int lastRight = lastNode.right_idx;
key = subMap.m.removeMiddleElement(lastNode, idx);
if (key == null && lastRight > lastNode.right_idx) {
// removed from right
offset--;
}
}
if (null != key) {
// the node has been cleared
Entry entry = subMap.m.find(key);
if (this.subMap.isInRange(key)) {
node = entry.node;
offset = entry.index;
boundaryPair = getBoundaryNode();
} else {
node = null;
}
}
if (node != null && !this.subMap.isInRange(node.keys[offset])){
node = null;
}
lastNode = null;
expectedModCount++;
} else {
throw new IllegalStateException();
}
}
} else {
throw new ConcurrentModificationException();
}
}
final void makeNext() {
if (expectedModCount != subMap.m.modCount) {
throw new ConcurrentModificationException();
} else if (node == null) {
throw new NoSuchElementException();
}
lastNode = node;
lastOffset = offset;
if (offset != lastNode.right_idx) {
offset++;
} else {
node = node.next;
if (node != null) {
offset = node.left_idx;
}
}
if (boundaryPair.node == lastNode
&& boundaryPair.index == lastOffset) {
node = null;
}
}
Entry createEntry(Node node, int index) {
TreeMap.Entry entry = new TreeMap.Entry(node.keys[index], node.values[index]);
entry.node = node;
entry.index = index;
return entry;
}
abstract TreeMap.Entry getStartNode();
abstract boolean hasNext();
abstract TreeMap.Entry getBoundaryNode();
}
private abstract static class AscendingSubMapIterator extends
AbstractSubMapIterator {
AscendingSubMapIterator(NavigableSubMap map) {
super(map);
}
final TreeMap.Entry getBoundaryNode() {
TreeMap.Entry entry = null;
if (subMap.toEnd) {
entry = subMap.hiInclusive ? subMap
.smallerOrEqualEntry(subMap.hi) : subMap
.smallerEntry(subMap.hi);
} else {
entry = subMap.theBiggestEntry();
}
if (entry == null){
entry = subMap.findStartNode();
}
return entry;
}
@Override
final TreeMap.Entry getStartNode() {
if (subMap.fromStart) {
return subMap.loInclusive ? subMap
.biggerOrEqualEntry(subMap.lo) : subMap
.biggerEntry(subMap.lo);
}
return subMap.theSmallestEntry();
}
TreeMap.Entry getNext() {
if (expectedModCount != subMap.m.modCount) {
throw new ConcurrentModificationException();
} else if (node == null) {
throw new NoSuchElementException();
}
lastNode = node;
lastOffset = offset;
if (offset != node.right_idx) {
offset++;
} else {
node = node.next;
if (node != null) {
offset = node.left_idx;
}
}
if (lastNode != null) {
boundaryPair = getBoundaryNode();
if (boundaryPair != null && boundaryPair.node == lastNode && boundaryPair.index == lastOffset) {
node = null;
}
return createEntry(lastNode, lastOffset);
}
return null;
}
@Override
public final boolean hasNext() {
return null!=node;
}
}
static class AscendingSubMapEntryIterator extends
AscendingSubMapIterator implements Iterator> {
AscendingSubMapEntryIterator(NavigableSubMap map) {
super(map);
}
public final Map.Entry next() {
return getNext();
}
}
static class AscendingSubMapKeyIterator extends
AscendingSubMapIterator implements Iterator {
AscendingSubMapKeyIterator(NavigableSubMap map) {
super(map);
}
public final K next() {
return getNext().key;
}
}
private abstract static class DescendingSubMapIterator extends
AbstractSubMapIterator {
DescendingSubMapIterator(NavigableSubMap map) {
super(map);
TreeMap.Entry entry;
if (map.fromStart){
entry = map.loInclusive ? map.m.findFloorEntry(map.lo) : map.m.findLowerEntry(map.lo);
} else {
entry = map.m.findBiggestEntry();
}
if (entry != null) {
if (!map.isInRange(entry.key)) {
node = null;
return;
}
node = entry.node;
offset = entry.index;
} else {
node = null;
return;
}
boundaryPair = getBoundaryNode();
if (boundaryPair != null){
if (map.m.keyCompare(boundaryPair.key,entry.key) > 0){
node = null;
}
}
if (map.toEnd && !map.hiInclusive){
// the last element may be the same with first one but it is not included
if (map.m.keyCompare(map.hi,entry.key) == 0){
node = null;
}
}
}
@Override
final TreeMap.Entry getStartNode() {
if (subMap.toEnd) {
return subMap.hiInclusive ? subMap
.smallerOrEqualEntry(subMap.hi) : subMap
.smallerEntry(subMap.hi);
}
return subMap.theBiggestEntry();
}
final TreeMap.Entry getBoundaryNode() {
if (subMap.toEnd) {
return subMap.hiInclusive ? subMap.m.findCeilingEntry(subMap.hi) : subMap.m.findHigherEntry(subMap.hi);
}
return subMap.m.findSmallestEntry();
}
TreeMap.Entry getNext() {
if (node == null) {
throw new NoSuchElementException();
}
if (expectedModCount != subMap.m.modCount) {
throw new ConcurrentModificationException();
}
lastNode = node;
lastOffset = offset;
if (offset != node.left_idx) {
offset--;
} else {
node = node.prev;
if (node != null) {
offset = node.right_idx;
}
}
boundaryPair = getBoundaryNode();
if (boundaryPair != null && boundaryPair.node == lastNode && boundaryPair.index == lastOffset) {
node = null;
}
return createEntry(lastNode, lastOffset);
}
@Override
public final boolean hasNext() {
return node != null;
}
public final void remove() {
if (expectedModCount == subMap.m.modCount) {
if (expectedModCount == subMap.m.modCount) {
K key = (node != null) ? node.keys[offset] : null;
if (lastNode != null) {
int idx = lastOffset;
if (idx == lastNode.left_idx){
subMap.m.removeLeftmost(lastNode);
} else if (idx == lastNode.right_idx) {
subMap.m.removeRightmost(lastNode);
} else {
subMap.m.removeMiddleElement(lastNode, idx);
}
if (null != key) {
// the node has been cleared
Entry entry = subMap.m.find(key);
node = entry.node;
offset = entry.index;
boundaryPair = getBoundaryNode();
} else {
node = null;
}
lastNode = null;
expectedModCount++;
} else {
throw new IllegalStateException();
}
}
} else {
throw new ConcurrentModificationException();
}
}
}
static class DescendingSubMapEntryIterator extends
DescendingSubMapIterator implements Iterator> {
DescendingSubMapEntryIterator(NavigableSubMap map) {
super(map);
}
public final Map.Entry next() {
return getNext();
}
}
static class DescendingSubMapKeyIterator extends
DescendingSubMapIterator implements Iterator {
DescendingSubMapKeyIterator(NavigableSubMap map) {
super(map);
}
public final K next() {
return getNext().key;
}
}
static final class SubMap extends AbstractMap implements
SortedMap {
private TreeMap backingMap;
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;
SubMap(K start, TreeMap map) {
backingMap = map;
hasStart = true;
startKey = start;
}
SubMap(K start, TreeMap map, K end) {
backingMap = map;
hasStart = hasEnd = true;
startKey = start;
endKey = end;
}
SubMap(K start, boolean hasStart, TreeMap map, K end, boolean hasEnd) {
backingMap = map;
this.hasStart = hasStart;
this.hasEnd = hasEnd;
startKey = start;
endKey = end;
}
SubMap(TreeMap map, K end) {
backingMap = map;
hasEnd = true;
endKey = end;
}
private void checkRange(K key) {
Comparator super K> cmp = backingMap.comparator;
if (cmp == null) {
java.lang.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();
}
}
}
private boolean isInRange(K key) {
Comparator super K> cmp = backingMap.comparator;
if (cmp == null) {
java.lang.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 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 && startKey != null) {
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 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> entrySet() {
if (entrySet == null) {
entrySet = new SubMapEntrySet(this);
}
return entrySet;
}
private void setFirstKey() {
if (firstKeyModCount == backingMap.modCount) {
return;
}
java.lang.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 = node.left_idx;
node = node.left;
} else if (result == 0) {
foundNode = node;
foundIndex = node.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 = node.right_idx;
break;
} else { /* search in node */
foundNode = node;
foundIndex = node.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;
}
}
}
// note, the original subMap is strange as the endKey is always
// excluded, to improve the performance here, we retain the original
// subMap, and keep the bound when firstkey = lastkey
boolean isBounded = true;
if (hasEnd && foundNode!=null) {
Comparator super K> cmp = backingMap.comparator;
if (cmp == null) {
isBounded = (toComparable(foundNode.keys[foundIndex]).compareTo(endKey) <= 0);
} else {
isBounded = (cmp.compare(foundNode.keys[foundIndex], endKey) <= 0);
}
}
if (foundNode != null
&& !isBounded) {
foundNode = null;
}
firstKeyNode = foundNode;
firstKeyIndex = foundIndex;
firstKeyModCount = backingMap.modCount;
}
public K firstKey() {
if (backingMap.size > 0 && !(startKey.equals(endKey))) {
if (!hasStart) {
Node 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 headMap(K endKey) {
Comparator super K> cmp = backingMap.comparator;
if (cmp == null) {
java.lang.Comparable object = toComparable(endKey);
if (hasStart && object.compareTo(startKey) < 0) {
throw new IllegalArgumentException();
}
if (hasEnd && object.compareTo(this.endKey) > 0) {
throw new IllegalArgumentException();
}
} else {
if (hasStart
&& backingMap.comparator().compare(endKey, startKey) < 0) {
throw new IllegalArgumentException();
}
if (hasEnd && backingMap.comparator().compare(endKey, this.endKey) >= 0) {
throw new IllegalArgumentException();
}
}
if (hasStart) {
return new SubMap(startKey, backingMap, endKey);
}
return new SubMap(backingMap, endKey);
}
@Override
public boolean isEmpty() {
Iterator it = this.keySet().iterator();
if (it.hasNext()) {
return false;
}
return true;
}
@Override
public Set keySet() {
if (keySet == null) {
keySet = new SubMapKeySet(this);
}
return keySet;
}
private void setLastKey() {
if (lastKeyModCount == backingMap.modCount) {
return;
}
java.lang.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;
// to be compatible with RI on null-key comparator
int result = object != null ? object.compareTo(keys[left_idx]) : -backingMap.comparator.compare(
keys[left_idx] , key);
//int result = - backingMap.cmp(object, keys[left_idx] , key);
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;
}
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;
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 && !(startKey.equals(endKey))) {
if (!hasEnd) {
Node node = maximum(backingMap.root);
if (node != null
&& checkLowerBound(node.keys[node.right_idx])) {
return node.keys[node.right_idx];
}
} else {
setLastKey();
if (lastKeyNode != null) {
java.lang.Comparable object = backingMap.comparator == null ? toComparable((K) endKey)
: null;
if (backingMap.cmp(object, endKey, lastKeyNode.keys[lastKeyIndex]) != 0) {
return lastKeyNode.keys[lastKeyIndex];
} else {
// according to subMap, it excludes the last element
if (lastKeyIndex != lastKeyNode.left_idx) {
object = backingMap.comparator == null ? toComparable((K) startKey)
: null;
// check if the element is smaller than the startkey, there's no lastkey
if (backingMap.cmp(object, startKey, lastKeyNode.keys[lastKeyIndex-1]) <= 0){
return lastKeyNode.keys[lastKeyIndex - 1];
}
} else {
Node last = lastKeyNode.prev;
if (last != null) {
return last.keys[last.right_idx];
}
}
}
}
}
}
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 subMap(K startKey, K endKey) {
checkRange(startKey);
Comparator super K> cmp = backingMap.comparator;
if (cmp == null) {
java.lang.Comparable object = toComparable(endKey);
if (hasStart && object.compareTo(startKey) < 0) {
throw new IllegalArgumentException();
}
if (hasEnd && object.compareTo(endKey) > 0) {
throw new IllegalArgumentException();
}
} else {
if (hasStart
&& backingMap.comparator().compare(endKey, this.startKey) < 0) {
throw new IllegalArgumentException();
}
if (hasEnd && backingMap.comparator().compare(endKey,this.endKey) > 0) {
throw new IllegalArgumentException();
}
}
Comparator super K> 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);
}
}
throw new IllegalArgumentException();
}
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;
}
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;
java.lang.Comparable object = backingMap.comparator == null ? toComparable((K) endKey)
: null;
if (to == null){
return 0;
} else if (backingMap.cmp(object, endKey, to.keys[toIndex]) != 0) {
if (toIndex != to.keys.length) {
toIndex++;
} else {
to = to.next;
toIndex = to == null ? 0 : to.left_idx;
}
}
} else {
to = maximum(backingMap.root);
toIndex = to == null ? 0 : to.right_idx;
}
if (to == null) {
return 0;
}
// the last element of submap if exist should be ignored
if (from == to) {
return toIndex - fromIndex + (hasEnd ? 0 : 1);
}
int sum = 0;
while (from != to) {
sum += (from.right_idx - fromIndex + 1);
from = from.next;
fromIndex = from.left_idx;
}
return sum + toIndex - fromIndex + (hasEnd ? 0 : 1);
}
}
static class SubMapValuesCollection extends AbstractCollection {
SubMap subMap;
public SubMapValuesCollection(SubMap subMap) {
this.subMap = subMap;
}
@Override
public boolean isEmpty() {
return subMap.isEmpty();
}
@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;
}
if (!subMap.hasEnd) {
return new UnboundedValueIterator(subMap.backingMap,
from, from == null ? 0 : fromIndex);
}
subMap.setLastKey();
Node to = subMap.lastKeyNode;
int toIndex = subMap.lastKeyIndex
+ (subMap.lastKeyNode != null
&& (!subMap.lastKeyNode.keys[subMap.lastKeyIndex].equals(subMap.endKey)) ? 1
: 0);
if (to != null
&& toIndex > to.right_idx) {
to = to.next;
toIndex = to != null ? to.left_idx : 0;
if (to == null){
// has endkey but it does not exist, thus return UnboundedValueIterator
return new UnboundedValueIterator(subMap.backingMap,
from, from == null ? 0 : fromIndex);
}
}
return new BoundedValueIterator(from, from == null ? 0
: fromIndex, subMap.backingMap, to,
to == null ? 0 : toIndex);
}
@Override
public int size() {
return subMap.size();
}
}
static class BoundedMapIterator extends AbstractMapIterator {
Node finalNode;
int finalOffset;
BoundedMapIterator(Node startNode, int startOffset,
TreeMap map, Node finalNode, int finalOffset) {
super(map, startNode, startOffset);
if (startNode ==null && finalNode == null){
// no elements
node = null;
return;
}
if (finalNode != null) {
this.finalNode = finalNode;
this.finalOffset = finalOffset;
} else {
Entry entry = map.findBiggestEntry();
if (entry != null) {
this.finalNode = entry.node;
this.finalOffset = entry.index;
} else {
node = null;
return;
}
}
if (startNode != null) {
if (node == this.finalNode && offset >= this.finalOffset) {
node = null;
} else if (this.finalOffset < this.finalNode.right_idx) {
java.lang.Comparable object = backingMap.comparator == null ? toComparable((K) startNode.keys[startOffset])
: null;
if (this.backingMap.cmp(object, node.keys[offset],
this.finalNode.keys[this.finalOffset]) > 0) {
node = null;
}
}
}
}
BoundedMapIterator(Node startNode, TreeMap map,
Node finalNode, int finalOffset) {
this(startNode, startNode.left_idx, map, finalNode, finalOffset);
}
BoundedMapIterator(Node startNode, int startOffset,
TreeMap map, Node finalNode) {
this(startNode, startOffset, map, finalNode, finalNode.right_idx);
}
void makeBoundedNext() {
if (node != null){
boolean endOfIterator = lastNode == finalNode && lastOffset == finalOffset;
if (endOfIterator) {
node = null;
} else {
makeNext();
}
}
}
public boolean hasNext(){
if (finalNode == node && finalOffset == offset) {
node = null;
}
return node != null;
}
}
static class BoundedEntryIterator extends BoundedMapIterator
implements Iterator> {
public BoundedEntryIterator(Node startNode, int startOffset,
TreeMap map, Node finalNode, int finalOffset) {
super(startNode, startOffset, map, finalNode, finalOffset);
}
public Map.Entry next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
makeBoundedNext();
int idx = lastOffset;
return new MapEntry(lastNode.keys[idx], lastNode.values[idx]);
}
}
static class BoundedKeyIterator extends BoundedMapIterator
implements Iterator {
public BoundedKeyIterator(Node startNode, int startOffset,
TreeMap map, Node finalNode, int finalOffset) {
super(startNode, startOffset, map, finalNode, finalOffset);
}
public K next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
makeBoundedNext();
return lastNode.keys[lastOffset];
}
}
static class BoundedValueIterator extends BoundedMapIterator
implements Iterator {
public BoundedValueIterator(Node startNode, int startOffset,
TreeMap map, Node finalNode, int finalOffset) {
super(startNode, startOffset, map, finalNode, finalOffset);
}
public V next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
makeBoundedNext();
return lastNode.values[lastOffset];
}
}
static class SubMapKeySet extends AbstractSet implements Set {
SubMap subMap;
SubMapKeySet(SubMap 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) {
return subMap.remove(object) != null;
}
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 (from == null){
return new BoundedKeyIterator(null, 0, subMap.backingMap, null, 0);
}
if (!subMap.hasEnd) {
return new UnboundedKeyIterator(subMap.backingMap,
from, from == null ? 0 : from.right_idx - fromIndex);
}
subMap.setLastKey();
Node to = subMap.lastKeyNode;
java.lang.Comparable object = subMap.backingMap.comparator == null ? toComparable((K) subMap.endKey)
: null;
int toIndex = subMap.lastKeyIndex
+ (subMap.lastKeyNode != null
&& (!subMap.lastKeyNode.keys[subMap.lastKeyIndex].equals(subMap.endKey)) ? 1
: 0);
if (subMap.lastKeyNode != null && toIndex > subMap.lastKeyNode.right_idx){
to = to.next;
toIndex = to != null ? to.left_idx : 0;
}
// no intial nor end key, return a unbounded iterator
if (to == null) {
return new UnboundedKeyIterator(subMap.backingMap, from,fromIndex);
} else
return new BoundedKeyIterator(from, from == null ? 0
: fromIndex, subMap.backingMap, to,
to == null ? 0 : toIndex);
}
}
/*
* Entry set of sub-maps, must override methods which check the range. add
* or addAll operations are disabled by default.
*/
static class SubMapEntrySet extends AbstractSet>
implements Set> {
SubMap subMap;
SubMapEntrySet(SubMap map) {
subMap = map;
}
@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 (from == null){
return new BoundedEntryIterator(null, 0, subMap.backingMap, null, 0);
}
if (!subMap.hasEnd) {
return new UnboundedEntryIterator(subMap.backingMap,
from, from == null ? 0 : from.right_idx - fromIndex);
}
subMap.setLastKey();
Node to = subMap.lastKeyNode;
java.lang.Comparable object = subMap.backingMap.comparator == null ? toComparable((K) subMap.endKey)
: null;
int toIndex = subMap.lastKeyIndex
+ (subMap.lastKeyNode != null
&& (!subMap.lastKeyNode.keys[subMap.lastKeyIndex].equals(subMap.endKey)) ? 1
: 0);
if (subMap.lastKeyNode != null && toIndex > subMap.lastKeyNode.right_idx){
to = to.next;
toIndex = to != null ? to.left_idx : 0;
}
if (to == null) {
return new UnboundedEntryIterator(subMap.backingMap, from,fromIndex);
} else
return new BoundedEntryIterator(from, from == null ? 0
: fromIndex, subMap.backingMap, to,
to == null ? 0 : toIndex);
}
@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 && subMap.containsKey(key) ) : v1.equals(v2);
}
}
return false;
}
@SuppressWarnings("unchecked")
@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;
}
}
static class AscendingSubMapEntrySet extends
AbstractSet> implements NavigableSet> {
boolean hasStart,hasEnd,startInclusive,endInclusive;
java.util.Map.Entry startEntry, lastentry;
NavigableSubMap map;
AscendingSubMapEntrySet(NavigableSubMap map) {
this.map = map;
}
AscendingSubMapEntrySet(NavigableSubMap map,
java.util.Map.Entry startEntry, boolean startInclusive,
java.util.Map.Entry endEntry, boolean endInclusive) {
if (startEntry != null) {
hasStart = true;
this.startEntry = startEntry;
this.startInclusive = startInclusive;
}
if (endEntry != null) {
hasEnd = true;
this.lastentry = endEntry;
this.endInclusive = endInclusive;
}
if (startEntry != null && endEntry != null) {
this.map = (NavigableSubMap) map.subMap(startEntry
.getKey(), startInclusive, endEntry.getKey(),
endInclusive);
return;
}
if (startEntry != null) {
this.map = (NavigableSubMap) map.tailMap(startEntry
.getKey(), startInclusive);
return;
}
if (endEntry != null) {
this.map = (NavigableSubMap) map.headMap(endEntry
.getKey(), endInclusive);
return;
}
this.map = map;
}
@Override
public final Iterator> iterator() {
return new AscendingSubMapEntryIterator(map);
}
@Override
public int size() {
int size = 0;
Iterator it = new AscendingSubMapEntryIterator(map);
while (it.hasNext()){
it.next();
size ++;
}
return size;
}
public java.util.Map.Entry ceiling(java.util.Map.Entry e) {
Map.Entry entry = map.ceilingEntry(e.getKey());
if (entry != null && map.isInRange(entry.getKey())){
return entry;
} else {
return null;
}
}
public Iterator> descendingIterator() {
return new DescendingSubMapEntrySet(map.descendingSubMap()).iterator();
}
public NavigableSet> descendingSet() {
return new DescendingSubMapEntrySet(map.descendingSubMap());
}
public java.util.Map.Entry floor(java.util.Map.Entry e) {
Map.Entry entry = map.floorEntry(e.getKey());
if (entry!= null && map.isInRange(entry.getKey())){
return entry;
} else {
return null;
}
}
public NavigableSet> headSet(
java.util.Map.Entry end, boolean endInclusive) {
boolean isInRange = true;
int result;
K endKey = end.getKey();
if (map.toEnd) {
result = (null != comparator()) ? comparator().compare(endKey,
map.hi) : toComparable(endKey).compareTo(map.hi);
isInRange = (!map.hiInclusive && endInclusive) ? result < 0
: result <= 0;
}
if (map.fromStart) {
result = (null != comparator()) ? comparator().compare(endKey,
map.lo) : toComparable(endKey).compareTo(map.lo);
isInRange = isInRange
&& ((!map.loInclusive && endInclusive) ? result > 0
: result >= 0);
}
if (isInRange) {
return new AscendingSubMapEntrySet(map, null, false,
end, endInclusive);
}
throw new IllegalArgumentException();
}
public java.util.Map.Entry higher(java.util.Map.Entry e) {
Comparator super K> cmp = map.m.comparator;
if (cmp == null) {
java.lang.Comparable object = toComparable(e.getKey());
if (hasStart && object.compareTo(startEntry.getKey()) < 0) {
return map.higherEntry(startEntry.getKey());
}
if (hasEnd && object.compareTo(lastentry.getKey()) >= 0) {
return null;
}
} else {
if (hasStart && cmp.compare(e.getKey(), startEntry.getKey()) < 0) {
return map.higherEntry(startEntry.getKey());
}
if (hasEnd && cmp.compare(e.getKey(), lastentry.getKey()) >= 0) {
return null;
}
}
return map.higherEntry(e.getKey());
}
public java.util.Map.Entry lower(java.util.Map.Entry e) {
Comparator super K> cmp = map.m.comparator;
if (cmp == null) {
java.lang.Comparable object = toComparable(e.getKey());
if (hasStart && object.compareTo(startEntry.getKey()) < 0) {
return null;
}
if (hasEnd && object.compareTo(lastentry.getKey()) >= 0) {
return map.lowerEntry(lastentry.getKey());
}
} else {
if (hasStart && cmp.compare(e.getKey(), startEntry.getKey()) < 0) {
return null;
}
if (hasEnd && cmp.compare(e.getKey(), lastentry.getKey()) >= 0) {
return map.lowerEntry(lastentry.getKey());
}
}
return map.lowerEntry(e.getKey());
}
public java.util.Map.Entry pollFirst() {
Map.Entry ret = map.firstEntry();
if (ret == null){
return null;
}
map.m.remove(ret.getKey());
return ret;
}
public java.util.Map.Entry pollLast() {
Map.Entry ret = map.lastEntry();
if (ret == null){
return null;
}
map.m.remove(ret.getKey());
return ret;
}
public NavigableSet> subSet(java.util.Map.Entry start, boolean startInclusive, java.util.Map.Entry end, boolean endInclusive) {
if (map.m.keyCompare(start.getKey(), end.getKey()) > 0) {
throw new IllegalArgumentException();
}
if (map.fromStart
&& ((!map.loInclusive && endInclusive) ? map.m.keyCompare(end.getKey(), map.lo) <= 0
: map.m.keyCompare(end.getKey(), map.lo) < 0)) {
throw new IllegalArgumentException();
}
if (map.toEnd
&& ((!map.hiInclusive && startInclusive) ? map.m.keyCompare(start.getKey(), map.hi) >= 0
: map.m.keyCompare(start.getKey(), map.hi) > 0)) {
throw new IllegalArgumentException();
}
return new AscendingSubMapEntrySet(map, start, startInclusive, end, endInclusive);
}
public NavigableSet> tailSet(java.util.Map.Entry start, boolean startInclusive) {
boolean isInRange = true;
int result;
if (map.toEnd) {
result = (null != comparator()) ? comparator().compare(start.getKey(),
map.hi) : toComparable(start.getKey()).compareTo(map.hi);
isInRange = (map.hiInclusive || !startInclusive) ? result <= 0
: result < 0;
}
if (map.fromStart) {
result = (null != comparator()) ? comparator().compare(start.getKey(),
map.lo) : toComparable(start.getKey()).compareTo(map.lo);
isInRange = isInRange
&& ((map.loInclusive || !startInclusive) ? result >= 0
: result > 0);
}
if (isInRange) {
return new AscendingSubMapEntrySet(map, start, startInclusive, null, false);
}
throw new IllegalArgumentException();
}
public Comparator comparator() {
return map.m.comparator;
}
public java.util.Map.Entry first() {
if (hasStart){
if (startInclusive){
return startEntry;
} else {
return map.floorEntry(startEntry.getKey());
}
}
java.util.Map.Entry ret = map.firstEntry();
if (ret == null){
throw new NoSuchElementException();
}
return ret;
}
public SortedSet> headSet(java.util.Map.Entry end) {
return headSet(end, false);
}
public java.util.Map.Entry last() {
if (hasEnd){
if (endInclusive){
return lastentry;
} else {
return map.ceilingEntry(lastentry.getKey());
}
}
java.util.Map.Entry ret = map.lastEntry();
if (ret == null){
throw new NoSuchElementException();
}
return ret;
}
public SortedSet> subSet(java.util.Map.Entry start, java.util.Map.Entry end) {
if ((null != comparator()) ? comparator().compare(start.getKey(), end.getKey()) > 0
: toComparable(start.getKey()).compareTo(end.getKey()) > 0) {
throw new IllegalArgumentException();
}
if (!map.isInRange(start.getKey())) {
throw new IllegalArgumentException();
}
if (!map.isInRange(end.getKey())) {
throw new IllegalArgumentException();
}
return new AscendingSubMapEntrySet(map, start, false, end, false);
}
public SortedSet> tailSet(java.util.Map.Entry start) {
return tailSet(start, false);
}
}
static class DescendingSubMapEntrySet extends
AbstractSet> implements NavigableSet> {
NavigableSubMap map;
DescendingSubMapEntrySet(NavigableSubMap map) {
this.map = map;
}
@Override
public final Iterator> iterator() {
return new DescendingSubMapEntryIterator(map);
}
@Override
public int size() {
int size = 0;
Iterator it = new DescendingSubMapEntryIterator(map);
while (it.hasNext()){
it.next();
size ++;
}
return size;
}
public java.util.Map.Entry ceiling(java.util.Map.Entry e) {
Entry node = map.m.findFloorEntry(e.getKey());
if (!map.checkUpperBound(node.key)){
node = map.findEndNode();
}
if (!map.checkLowerBound(node.key)){
java.lang.Comparable object = map.comparator() == null ? toComparable((K) e.getKey())
: null;
TreeMap.Entry first = map.loInclusive ? map.m.findFloorEntry(map.lo) :map.m.findLowerEntry(map.lo);
if (first != null && map.cmp(object, e.getKey(), first.getKey()) <= 0){
node = first;
} else {
node = null;
}
}
return node;
}
public Iterator> descendingIterator() {
return descendingSet().iterator();
}
public NavigableSet