swim.util.OrderedMapView Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of swim-util Show documentation
Show all versions of swim-util Show documentation
Extended collection, iterator, and builder interfaces, lightweight cache sets and maps, and other foundational utilities
// Copyright 2015-2019 SWIM.AI inc.
//
// Licensed 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 swim.util;
import java.util.Comparator;
import java.util.Iterator;
import java.util.Map;
final class OrderedMapView implements OrderedMap {
final OrderedMap map;
final K fromKey;
final K toKey;
OrderedMapView(OrderedMap map, K fromKey, K toKey) {
this.map = map;
this.fromKey = fromKey;
this.toKey = toKey;
}
@Override
public boolean isEmpty() {
return size() == 0;
}
@Override
public int size() {
int fromIndex;
if (this.fromKey != null) {
fromIndex = this.map.indexOf(this.fromKey);
if (fromIndex < 0) {
fromIndex = -(fromIndex + 1);
}
} else {
fromIndex = 0;
}
int toIndex;
if (this.toKey != null) {
toIndex = this.map.indexOf(this.toKey);
if (toIndex < 0) {
toIndex = -(toIndex + 1);
} else {
toIndex += 1;
}
} else {
toIndex = this.map.size();
}
return toIndex - fromIndex;
}
@Override
public boolean containsKey(Object key) {
return (this.fromKey == null || compareKey(this.fromKey, key) >= 0)
&& (this.toKey == null || compareKey(key, this.toKey) < 0)
&& this.map.containsKey(key);
}
@Override
public boolean containsValue(Object value) {
final Cursor cursor = valueIterator();
while (cursor.hasNext()) {
if (value == null ? cursor.next() == null : value.equals(cursor.next())) {
return true;
}
}
return false;
}
@Override
public int indexOf(Object key) {
if ((this.fromKey == null || compareKey(this.fromKey, key) >= 0)
&& (this.toKey == null || compareKey(key, this.toKey) < 0)) {
int fromIndex;
if (this.fromKey != null) {
fromIndex = this.map.indexOf(this.fromKey);
if (fromIndex < 0) {
fromIndex = -(fromIndex + 1);
}
} else {
fromIndex = 0;
}
final int keyIndex = this.map.indexOf(key);
if (keyIndex >= 0) {
return keyIndex - fromIndex;
} else {
return keyIndex + fromIndex;
}
} else {
throw new IllegalArgumentException(key.toString());
}
}
@Override
public V get(Object key) {
if ((this.fromKey == null || compareKey(this.fromKey, key) >= 0)
&& (this.toKey == null || compareKey(key, this.toKey) < 0)) {
return this.map.get(key);
} else {
return null;
}
}
@Override
public Entry getEntry(Object key) {
if ((this.fromKey == null || compareKey(this.fromKey, key) >= 0)
&& (this.toKey == null || compareKey(key, this.toKey) < 0)) {
return this.map.getEntry(key);
} else {
return null;
}
}
@Override
public Entry getIndex(int index) {
final Cursor> cursor = iterator();
int i = 0;
while (i < index && cursor.hasNext()) {
cursor.step();
i += 1;
}
if (i == index && cursor.hasNext()) {
return cursor.next();
} else {
throw new IndexOutOfBoundsException(Integer.toString(index));
}
}
@Override
public Entry firstEntry() {
Entry nextEntry;
if (this.fromKey != null) {
nextEntry = this.map.getEntry(this.fromKey);
if (nextEntry != null) {
return nextEntry;
} else {
nextEntry = this.map.nextEntry(this.fromKey);
}
} else {
nextEntry = this.map.firstEntry();
}
if (this.toKey == null || nextEntry != null && compareKey(nextEntry.getKey(), this.toKey) < 0) {
return nextEntry;
} else {
return null;
}
}
@Override
public K firstKey() {
final K nextKey;
if (this.fromKey != null) {
if (this.map.containsKey(this.fromKey)) {
return this.fromKey;
} else {
nextKey = this.map.nextKey(this.fromKey);
}
} else {
nextKey = this.map.firstKey();
}
if (this.toKey == null || nextKey != null && compareKey(nextKey, this.toKey) < 0) {
return nextKey;
} else {
return null;
}
}
@Override
public V firstValue() {
final K firstKey = firstKey();
if (firstKey != null) {
return this.map.get(firstKey);
} else {
return null;
}
}
@Override
public Entry lastEntry() {
final Entry previousEntry;
if (this.toKey != null) {
previousEntry = this.map.previousEntry(this.toKey);
} else {
previousEntry = this.map.lastEntry();
}
if (this.fromKey == null || previousEntry != null && compareKey(this.fromKey, previousEntry.getKey()) <= 0) {
return previousEntry;
} else {
return null;
}
}
@Override
public K lastKey() {
final K previousKey;
if (this.toKey != null) {
previousKey = this.map.previousKey(this.toKey);
} else {
previousKey = this.map.lastKey();
}
if (this.fromKey == null || previousKey != null && compareKey(this.fromKey, previousKey) <= 0) {
return previousKey;
} else {
return null;
}
}
@Override
public V lastValue() {
final K lastKey = lastKey();
if (lastKey != null) {
return this.map.get(lastKey);
} else {
return null;
}
}
@Override
public Entry nextEntry(K key) {
final Entry nextEntry = this.map.nextEntry(key);
if (nextEntry != null && (this.toKey == null || compareKey(nextEntry.getKey(), this.toKey) < 0)) {
return nextEntry;
} else {
return null;
}
}
@Override
public K nextKey(K key) {
final K nextKey = this.map.nextKey(key);
if (nextKey != null && (this.toKey == null || compareKey(nextKey, this.toKey) < 0)) {
return nextKey;
} else {
return null;
}
}
@Override
public V nextValue(K key) {
final K nextKey = nextKey(key);
if (nextKey != null) {
return this.map.get(nextKey);
} else {
return null;
}
}
@Override
public Entry previousEntry(K key) {
final Entry previousEntry = this.map.previousEntry(key);
if (previousEntry != null && (this.fromKey == null || compareKey(this.fromKey, previousEntry.getKey()) <= 0)) {
return previousEntry;
} else {
return null;
}
}
@Override
public K previousKey(K key) {
final K previousKey = this.map.previousKey(key);
if (previousKey != null && (this.fromKey == null || compareKey(this.fromKey, previousKey) <= 0)) {
return previousKey;
} else {
return null;
}
}
@Override
public V previousValue(K key) {
final K previousKey = previousKey(key);
if (previousKey != null) {
return this.map.get(previousKey);
} else {
return null;
}
}
@Override
public V put(K key, V newValue) {
if ((this.fromKey == null || compareKey(this.fromKey, key) <= 0)
&& (this.toKey == null || compareKey(key, this.toKey) < 0)) {
return this.map.put(key, newValue);
} else {
throw new IllegalArgumentException(key.toString());
}
}
@Override
public V remove(Object key) {
if ((this.fromKey == null || compareKey(this.fromKey, key) <= 0)
&& (this.toKey == null || compareKey(key, this.toKey) < 0)) {
return this.map.remove(key);
} else {
return null;
}
}
@Override
public void clear() {
final Cursor cursor = keyIterator();
while (cursor.hasNext()) {
cursor.step();
cursor.remove();
}
}
@Override
public OrderedMap headMap(K toKey) {
if (compareKey(toKey, this.toKey) > 0) {
toKey = this.toKey;
}
return new OrderedMapView(this.map, this.fromKey, toKey);
}
@Override
public OrderedMap tailMap(K fromKey) {
if (compareKey(fromKey, this.fromKey) < 0) {
fromKey = this.fromKey;
}
return new OrderedMapView(this.map, fromKey, this.toKey);
}
@Override
public OrderedMap subMap(K fromKey, K toKey) {
if (compareKey(fromKey, this.fromKey) < 0) {
fromKey = this.fromKey;
}
if (compareKey(toKey, this.toKey) > 0) {
toKey = this.toKey;
}
return new OrderedMapView(this.map, fromKey, toKey);
}
@Override
public OrderedMapCursor iterator() {
int index = this.map.indexOf(this.fromKey);
if (index < 0) {
index = -(index + 1);
}
final OrderedMapCursor cursor = this.map.iterator();
cursor.skip(index - 1);
return new OrderedMapViewCursor(this.map, cursor, this.fromKey, this.toKey);
}
@Override
public Comparator super K> comparator() {
return this.map.comparator();
}
@SuppressWarnings("unchecked")
private int compareKey(Object x, Object y) {
final Comparator