
org.javersion.util.AbstractTreeMap Maven / Gradle / Ivy
/*
* Copyright 2013 Samppa Saarela
*
* 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 org.javersion.util;
import static com.google.common.collect.Iterables.transform;
import static org.javersion.util.AbstractRedBlackTree.Color.RED;
import java.util.Comparator;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import org.javersion.util.AbstractTreeMap.Node;
import com.google.common.base.Objects;
import com.google.common.collect.Iterables;
import com.google.common.collect.Iterators;
public abstract class AbstractTreeMap>
extends AbstractRedBlackTree, This> implements Iterable> {
protected AbstractTreeMap() {
super();
}
protected AbstractTreeMap(Comparator super K> comparator) {
super(comparator);
}
public abstract int size();
protected abstract Node root();
protected UpdateContext> updateContext() {
return updateContext(null);
}
protected UpdateContext> updateContext(Merger> merger) {
return new UpdateContext>(1, merger);
}
public V get(Object key) {
Node node = find(root(), key);
return node != null ? node.value : null;
}
public V max() {
Node max = findMax(root());
return max != null ? max.value : null;
}
public V min() {
Node min = findMin(root());
return min != null ? min.value : null;
}
public This assoc(K key, V value) {
UpdateContext> context = updateContext();
return doAdd(context, root(), new Node(context, key, value, RED));
}
@SuppressWarnings("unchecked")
public This assocAll(Map extends K, ? extends V> map) {
final UpdateContext> context = updateContext();
return (This) doAddAll(context, root(), transform(map.entrySet(), (entry) -> entryToNode(entry, context)));
}
private Node entryToNode(Entry extends K, ? extends V> entry, UpdateContext> context) {
if (entry instanceof Node) {
return (Node) entry;
} else {
return new Node(context, entry.getKey(), entry.getValue(), RED);
}
}
public This dissoc(Object keyObj) {
return doRemove(updateContext(), root(), keyObj);
}
public This assocAll(Iterable> entries) {
final UpdateContext> context = updateContext();
return (This) doAddAll(context, root(), transform(entries, (entry) -> entryToNode(entry, context)));
}
public This merge(K key, V value, Merger> merger) {
final UpdateContext> context = updateContext(merger);
return doAdd(context, root(), new Node(context, key, value, RED));
}
public This mergeAll(Map extends K, ? extends V> map, Merger> merger) {
final UpdateContext> context = updateContext(merger);
return (This) doAddAll(context, root(), transform(map.entrySet(), (entry) -> entryToNode(entry, context)));
}
public This mergeAll(Iterable> entries, Merger> merger) {
final UpdateContext> context = updateContext(merger);
return (This) doAddAll(context, root(), transform(entries, (entry) -> entryToNode(entry, context)));
}
public This dissoc(Object key, Merger> merger) {
final UpdateContext> context = updateContext(merger);
return doRemove(context, root(), key);
}
public boolean containsKey(Object key) {
return find(root(), key) != null;
}
@Override
public Iterator> iterator() {
return iterator(true);
}
public Iterator> iterator(boolean asc) {
return Iterators.transform(doIterator(root(), true), Map.Entry.class::cast);
}
public Iterable> range(K from, K to) {
return range(from, true, to, false, true);
}
public Iterable> range(K from, K to, boolean asc) {
return range(from, true, to, false, asc);
}
public Iterable> range(final K from, final boolean fromInclusive, final K to, final boolean toInclusive) {
return range(from, fromInclusive, to, toInclusive, true);
}
public Iterable> range(final K from, final boolean fromInclusive, final K to, final boolean toInclusive, final boolean asc) {
return new Iterable>() {
@Override
public Iterator> iterator() {
return Iterators.transform(doRangeIterator(root(), asc, from, fromInclusive, to, toInclusive), Map.Entry.class::cast);
}
};
}
public Iterable keys() {
return Iterables.transform(this, MapUtils.mapKeyFunction());
}
public Iterable values() {
return Iterables.transform(this, MapUtils.mapValueFunction());
}
static class Node extends AbstractRedBlackTree.Node> implements Map.Entry{
V value;
public Node(UpdateContext super Node> context, K key, V value, Color color) {
this(context, key, value, color, null, null);
}
public Node(UpdateContext super Node> context, K key, V value, Color color, Node left, Node right) {
super(context, key, color, left, right);
this.value = value;
}
@Override
public K getKey() {
return key;
}
@Override
public V getValue() {
return value;
}
@Override
public Node self() {
return this;
}
@Override
public V setValue(V value) {
throw new UnsupportedOperationException();
}
@Override
protected Node cloneWith(UpdateContext super Node> currentContext) {
return new Node(currentContext, key, value, color, left, right);
}
@Override
protected Node replaceWith(UpdateContext super Node> currentContext, Node node) {
if (node == this || Objects.equal(this.value, node.value)) {
return null;
}
else if (context.isSameAs(currentContext)) {
this.value = node.value;
return this;
}
else if (node.context.isSameAs(currentContext)) {
node.color = this.color;
node.left = this.left;
node.right = this.right;
return node;
}
else {
// This should never happen
throw new IllegalStateException("node from another UpdateContext");
}
}
public String toString() {
return getKey() + ": " + getValue();
}
}
static class EntrySpliterator extends RBSpliterator, Node> {
private final Comparator super K> comparator;
public EntrySpliterator(Node root, int size, Comparator super K> comparator, boolean immutable) {
super(root, size, SORTED | DISTINCT | (immutable ? IMMUTABLE : 0));
this.comparator = comparator;
}
protected EntrySpliterator(int sizeEstimate, Comparator super K> comparator, boolean immutable) {
super(sizeEstimate, SORTED | DISTINCT | (immutable ? IMMUTABLE : 0));
this.comparator = comparator;
}
@Override
protected RBSpliterator, Node> newSpliterator(int sizeEstimate) {
return new EntrySpliterator<>(sizeEstimate, comparator, hasCharacteristics(IMMUTABLE));
}
@Override
protected Entry apply(Node node) {
return node;
}
@Override
public Comparator super Map.Entry> getComparator() {
return Map.Entry.comparingByKey(comparator);
}
}
static class KeySpliterator extends RBSpliterator> {
private final Comparator super K> comparator;
public KeySpliterator(Node root, int size, Comparator super K> comparator, boolean immutable) {
super(root, size, SORTED | DISTINCT | (immutable ? IMMUTABLE : 0));
this.comparator = comparator;
}
protected KeySpliterator(int sizeEstimate, Comparator super K> comparator, boolean immutable) {
super(sizeEstimate, SORTED | DISTINCT | (immutable ? IMMUTABLE : 0));
this.comparator = comparator;
}
@Override
protected RBSpliterator> newSpliterator(int sizeEstimate) {
return new KeySpliterator<>(sizeEstimate, comparator, hasCharacteristics(IMMUTABLE));
}
@Override
protected K apply(Node node) {
return node.key;
}
@Override
public Comparator super K> getComparator() {
return comparator;
}
}
static class ValueSpliterator extends RBSpliterator> {
private final Comparator super K> comparator;
public ValueSpliterator(Node root, int size, Comparator super K> comparator, boolean immutable) {
super(root, size, (immutable ? IMMUTABLE : 0));
this.comparator = comparator;
}
protected ValueSpliterator(int sizeEstimate, Comparator super K> comparator, boolean immutable) {
super(sizeEstimate, (immutable ? IMMUTABLE : 0));
this.comparator = comparator;
}
@Override
protected RBSpliterator> newSpliterator(int sizeEstimate) {
return new ValueSpliterator<>(sizeEstimate, comparator, hasCharacteristics(IMMUTABLE));
}
@Override
protected V apply(Node node) {
return node.value;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy