javaslang.collection.TreeMap Maven / Gradle / Ivy
/* / \____ _ _ ____ ______ / \ ____ __ _ _____
* / / \/ \ / \/ \ / /\__\/ // \/ \ / / _ \ Javaslang
* _/ / /\ \ \/ / /\ \\__\\ \ // /\ \ /\\/ \__/ / Copyright 2014-now Daniel Dietrich
* /___/\_/ \_/\____/\_/ \_/\__\/__/___\_/ \_// \__/_____/ Licensed under the Apache License, Version 2.0
*/
package javaslang.collection;
import javaslang.Tuple;
import javaslang.Tuple2;
import javaslang.control.Match;
import javaslang.control.Option;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.function.*;
import java.util.stream.Collector;
import static javaslang.collection.Comparators.naturalComparator;
/**
* SortedMap implementation, backed by a Red/Black Tree.
*
* @param Key type
* @param Value type
* @author Daniel Dietrich
* @since 2.0.0
*/
// DEV-NOTE: use entries.min().get() in favor of iterator().next(), it is faster!
public final class TreeMap implements SortedMap, Serializable {
private static final long serialVersionUID = 1L;
private final RedBlackTree> entries;
private TreeMap(RedBlackTree> entries) {
this.entries = entries;
}
/**
* Returns a {@link java.util.stream.Collector} which may be used in conjunction with
* {@link java.util.stream.Stream#collect(java.util.stream.Collector)} to obtain a
* {@link javaslang.collection.TreeMap}.
*
* @param The key type
* @param The value type
* @return A {@link javaslang.collection.TreeMap} Collector.
*/
public static Collector, ArrayList>, TreeMap> collector() {
final Supplier>> supplier = ArrayList::new;
final BiConsumer>, Tuple2> accumulator = ArrayList::add;
final BinaryOperator>> combiner = (left, right) -> {
left.addAll(right);
return left;
};
final Comparator super K> comparator = naturalComparator();
final Function>, TreeMap> finisher = list -> TreeMap.ofEntries(comparator, list);
return Collector.of(supplier, accumulator, combiner, finisher);
}
/**
* Returns the empty TreeMap. The underlying key comparator is the natural comparator of K.
*
* @param The key type
* @param The value type
* @return A new empty TreeMap.
*/
public static , V> TreeMap empty() {
return empty((Comparator super K> & Serializable) K::compareTo);
}
/**
* Returns the empty TreeMap using the given key comparator.
*
* @param The key type
* @param The value type
* @param keyComparator The comparator used to sort the entries by their key.
* @return A new empty TreeMap.
*/
public static TreeMap empty(Comparator super K> keyComparator) {
Objects.requireNonNull(keyComparator, "keyComparator is null");
return new TreeMap<>(RedBlackTree.empty(new EntryComparator<>(keyComparator)));
}
/**
* Narrows a widened {@code TreeMap extends K, ? extends V>} to {@code TreeMap}
* by performing a type safe-cast. This is eligible because immutable/read-only
* collections are covariant.
*
* CAUTION: If {@code K} is narrowed, the underlying {@code Comparator} might fail!
*
* @param treeMap A {@code TreeMap}.
* @param Key type
* @param Value type
* @return the given {@code treeMap} instance as narrowed type {@code TreeMap}.
*/
@SuppressWarnings("unchecked")
static TreeMap narrow(TreeMap extends K, ? extends V> treeMap) {
return (TreeMap) treeMap;
}
/**
* Returns a singleton {@code TreeMap}, i.e. a {@code TreeMap} of one entry.
* The underlying key comparator is the natural comparator of K.
*
* @param The key type
* @param The value type
* @param entry A map entry.
* @return A new TreeMap containing the given entry.
*/
public static , V> TreeMap of(Tuple2 extends K, ? extends V> entry) {
return of((Comparator super K> & Serializable) K::compareTo, entry);
}
/**
* Creates a TreeMap of the given list of key-value pairs.
*
* @param pairs A list of key-value pairs
* @param The key type
* @param The value type
* @return A new Map containing the given entries
*/
@SuppressWarnings("unchecked")
public static TreeMap of(Object... pairs) {
Objects.requireNonNull(pairs, "pairs is null");
if ((pairs.length & 1) != 0) {
throw new IllegalArgumentException("Odd length of key-value pairs list");
}
RedBlackTree> result = RedBlackTree.empty();
for (int i = 0; i < pairs.length; i += 2) {
result = result.insert(Tuple.of((K) pairs[i], (V) pairs[i + 1]));
}
return new TreeMap<>(result);
}
/**
* Returns a {@code TreeMap}, from a source java.util.Map.
*
* @param map A map entry.
* @param The key type
* @param The value type
* @return A new Map containing the given map
*/
public static , V> TreeMap ofAll(java.util.Map extends K, ? extends V> map) {
Objects.requireNonNull(map, "map is null");
RedBlackTree> result = RedBlackTree.empty();
for (java.util.Map.Entry extends K, ? extends V> entry : map.entrySet()) {
result = result.insert(Tuple.of(entry.getKey(), entry.getValue()));
}
return new TreeMap<>(result);
}
/**
* Returns a singleton {@code TreeMap}, i.e. a {@code TreeMap} of one entry using a specific key comparator.
*
* @param The key type
* @param The value type
* @param entry A map entry.
* @param keyComparator The comparator used to sort the entries by their key.
* @return A new TreeMap containing the given entry.
*/
public static TreeMap of(Comparator super K> keyComparator, Tuple2 extends K, ? extends V> entry) {
Objects.requireNonNull(keyComparator, "keyComparator is null");
Objects.requireNonNull(entry, "entry is null");
return TreeMap. empty(keyComparator).put(entry);
}
/**
* Returns a singleton {@code TreeMap}, i.e. a {@code TreeMap} of one element.
*
* @param key A singleton map key.
* @param value A singleton map value.
* @param The key type
* @param The value type
* @return A new Map containing the given entry
*/
public static , V> TreeMap of(K key, V value) {
return of((Comparator super K> & Serializable) K::compareTo, key, value);
}
/**
* Returns a singleton {@code TreeMap}, i.e. a {@code TreeMap} of one element.
*
* @param key A singleton map key.
* @param value A singleton map value.
* @param The key type
* @param The value type
* @param keyComparator The comparator used to sort the entries by their key.
* @return A new Map containing the given entry
*/
public static , V> TreeMap of(Comparator super K> keyComparator, K key, V value) {
Objects.requireNonNull(keyComparator, "keyComparator is null");
return TreeMap. empty(keyComparator).put(key, value);
}
/**
* Returns a TreeMap containing {@code n} values of a given Function {@code f}
* over a range of integer values from 0 to {@code n - 1}.
*
* @param The key type
* @param The value type
* @param keyComparator The comparator used to sort the entries by their key
* @param n The number of elements in the TreeMap
* @param f The Function computing element values
* @return A TreeMap consisting of elements {@code f(0),f(1), ..., f(n - 1)}
* @throws NullPointerException if {@code keyComparator} or {@code f} are null
*/
@SuppressWarnings("unchecked")
public static TreeMap tabulate(Comparator super K> keyComparator, int n, Function super Integer, ? extends Tuple2 extends K, ? extends V>> f) {
Objects.requireNonNull(keyComparator, "keyComparator is null");
Objects.requireNonNull(f, "f is null");
return ofEntries(keyComparator, Collections.tabulate(n, (Function super Integer, ? extends Tuple2>) f));
}
/**
* Returns a TreeMap containing {@code n} values of a given Function {@code f}
* over a range of integer values from 0 to {@code n - 1}.
* The underlying key comparator is the natural comparator of K.
*
* @param The key type
* @param The value type
* @param n The number of elements in the TreeMap
* @param f The Function computing element values
* @return A TreeMap consisting of elements {@code f(0),f(1), ..., f(n - 1)}
* @throws NullPointerException if {@code f} is null
*/
public static , V> TreeMap tabulate(int n, Function super Integer, ? extends Tuple2 extends K, ? extends V>> f) {
Objects.requireNonNull(f, "f is null");
return tabulate((Comparator super K> & Serializable) K::compareTo, n, f);
}
/**
* Returns a TreeMap containing {@code n} values supplied by a given Supplier {@code s}.
*
* @param The key type
* @param The value type
* @param keyComparator The comparator used to sort the entries by their key
* @param n The number of elements in the TreeMap
* @param s The Supplier computing element values
* @return A TreeMap of size {@code n}, where each element contains the result supplied by {@code s}.
* @throws NullPointerException if {@code keyComparator} or {@code s} are null
*/
@SuppressWarnings("unchecked")
public static TreeMap fill(Comparator super K> keyComparator, int n, Supplier extends Tuple2 extends K, ? extends V>> s) {
Objects.requireNonNull(keyComparator, "keyComparator is null");
Objects.requireNonNull(s, "s is null");
return ofEntries(keyComparator, Collections.fill(n, (Supplier extends Tuple2>) s));
}
/**
* Returns a TreeMap containing {@code n} values supplied by a given Supplier {@code s}.
* The underlying key comparator is the natural comparator of K.
*
* @param The key type
* @param The value type
* @param n The number of elements in the TreeMap
* @param s The Supplier computing element values
* @return A TreeMap of size {@code n}, where each element contains the result supplied by {@code s}.
* @throws NullPointerException if {@code s} is null
*/
public static , V> TreeMap fill(int n, Supplier extends Tuple2 extends K, ? extends V>> s) {
Objects.requireNonNull(s, "s is null");
return fill((Comparator super K> & Serializable) K::compareTo, n, s);
}
/**
* Creates a {@code TreeMap} of the given entries using the natural key comparator.
*
* @param The key type
* @param The value type
* @param entries Map entries
* @return A new TreeMap containing the given entries.
*/
@SuppressWarnings("varargs")
@SafeVarargs
public static , V> TreeMap ofEntries(Tuple2 extends K, ? extends V>... entries) {
return ofEntries((Comparator super K> & Serializable) K::compareTo, entries);
}
/**
* Creates a {@code TreeMap} of the given entries using the natural key comparator.
*
* @param The key type
* @param The value type
* @param entries Map entries
* @return A new TreeMap containing the given entries.
*/
@SuppressWarnings("varargs")
@SafeVarargs
public static , V> TreeMap ofEntries(java.util.Map.Entry extends K, ? extends V>... entries) {
return ofEntries((Comparator super K> & Serializable) K::compareTo, entries);
}
/**
* Creates a {@code TreeMap} of the given entries using the given key comparator.
*
* @param The key type
* @param The value type
* @param entries Map entries
* @param keyComparator A key comparator
* @return A new TreeMap containing the given entries.
*/
@SuppressWarnings("unchecked")
@SafeVarargs
public static TreeMap ofEntries(Comparator super K> keyComparator, Tuple2 extends K, ? extends V>... entries) {
Objects.requireNonNull(keyComparator, "keyComparator is null");
Objects.requireNonNull(entries, "entries is null");
RedBlackTree> tree = RedBlackTree.empty(new EntryComparator<>(keyComparator));
for (Tuple2 extends K, ? extends V> entry : entries) {
tree = tree.insert((Tuple2) entry);
}
return tree.isEmpty() ? TreeMap.empty(keyComparator) : new TreeMap<>(tree);
}
/**
* Creates a {@code TreeMap} of the given entries using the given key comparator.
*
* @param The key type
* @param The value type
* @param entries Map entries
* @param keyComparator A key comparator
* @return A new TreeMap containing the given entries.
*/
@SafeVarargs
public static TreeMap ofEntries(Comparator super K> keyComparator, java.util.Map.Entry extends K, ? extends V>... entries) {
Objects.requireNonNull(keyComparator, "keyComparator is null");
Objects.requireNonNull(entries, "entries is null");
RedBlackTree> tree = RedBlackTree.empty(new EntryComparator<>(keyComparator));
for (java.util.Map.Entry extends K, ? extends V> entry : entries) {
tree = tree.insert(Tuple.of(entry.getKey(), entry.getValue()));
}
return tree.isEmpty() ? TreeMap.empty(keyComparator) : new TreeMap<>(tree);
}
/**
* Creates a {@code TreeMap} of the given entries.
*
* @param The key type
* @param The value type
* @param entries Map entries
* @return A new TreeMap containing the given entries.
*/
public static , V> TreeMap ofEntries(
Iterable extends Tuple2 extends K, ? extends V>> entries) {
return ofEntries((Comparator super K> & Serializable) K::compareTo, entries);
}
/**
* Creates a {@code TreeMap} of the given entries.
*
* @param The key type
* @param The value type
* @param entries Map entries
* @param keyComparator A key comparator
* @return A new TreeMap containing the given entries.
*/
@SuppressWarnings("unchecked")
public static TreeMap ofEntries(Comparator super K> keyComparator, Iterable extends Tuple2 extends K, ? extends V>> entries) {
Objects.requireNonNull(keyComparator, "keyComparator is null");
Objects.requireNonNull(entries, "entries is null");
if (entries instanceof TreeMap) {
return (TreeMap) entries;
} else {
RedBlackTree> tree = RedBlackTree.empty(new EntryComparator<>(keyComparator));
for (Tuple2 extends K, ? extends V> entry : entries) {
tree = tree.insert((Tuple2) entry);
}
return new TreeMap<>(tree);
}
}
@Override
public TreeMap bimap(Function super K, ? extends K2> keyMapper, Function super V, ? extends V2> valueMapper) {
return bimap(naturalComparator(), keyMapper, valueMapper);
}
@Override
public TreeMap bimap(Comparator super K2> keyComparator,
Function super K, ? extends K2> keyMapper, Function super V, ? extends V2> valueMapper) {
Objects.requireNonNull(keyMapper, "keyMapper is null");
Objects.requireNonNull(valueMapper, "valueMapper is null");
return createTreeMap(new EntryComparator<>(keyComparator),
entries.iterator().map(entry -> Tuple.of(keyMapper.apply(entry._1), valueMapper.apply(entry._2))));
}
@Override
public TreeMap clear() {
return isEmpty() ? this : new TreeMap<>(entries.clear());
}
@Override
public TreeMap distinct() {
return this;
}
@Override
public TreeMap distinctBy(Comparator super Tuple2> comparator) {
Objects.requireNonNull(comparator, "comparator is null");
return createTreeMap(entries.comparator(), iterator().distinctBy(comparator));
}
@Override
public TreeMap distinctBy(Function super Tuple2, ? extends U> keyExtractor) {
Objects.requireNonNull(keyExtractor, "keyExtractor is null");
return createTreeMap(entries.comparator(), iterator().distinctBy(keyExtractor));
}
@Override
public TreeMap drop(long n) {
if (n <= 0) {
return this;
} else {
return createTreeMap(entries.comparator(), iterator().drop(n));
}
}
@Override
public TreeMap dropRight(long n) {
if (n <= 0) {
return this;
} else {
return createTreeMap(entries.comparator(), iterator().dropRight(n));
}
}
@Override
public TreeMap dropUntil(Predicate super Tuple2> predicate) {
Objects.requireNonNull(predicate, "predicate is null");
return dropWhile(predicate.negate());
}
@Override
public TreeMap dropWhile(Predicate super Tuple2> predicate) {
Objects.requireNonNull(predicate, "predicate is null");
return createTreeMap(entries.comparator(), iterator().dropWhile(predicate));
}
@Override
public boolean containsKey(K key) {
final V ignored = null;
return entries.contains(new Tuple2<>(key, ignored));
}
@Override
public boolean containsValue(V value) {
return iterator().map(Tuple2::_2).contains(value);
}
@Override
public TreeMap filter(Predicate super Tuple2> predicate) {
Objects.requireNonNull(predicate, "predicate is null");
return createTreeMap(entries.comparator(), entries.iterator().filter(predicate));
}
@Override
public TreeMap flatMap(BiFunction super K, ? super V, ? extends Iterable>> mapper) {
return flatMap(naturalComparator(), mapper);
}
@Override
public TreeMap flatMap(Comparator super K2> keyComparator,
BiFunction super K, ? super V, ? extends Iterable>> mapper) {
Objects.requireNonNull(mapper, "mapper is null");
return createTreeMap(new EntryComparator<>(keyComparator),
entries.iterator().flatMap(entry -> mapper.apply(entry._1, entry._2)));
}
@Override
public U foldRight(U zero, BiFunction super Tuple2, ? super U, ? extends U> f) {
Objects.requireNonNull(f, "f is null");
return iterator().foldRight(zero, f);
}
@Override
public Option get(K key) {
final V ignored = null;
return entries.find(new Tuple2<>(key, ignored)).map(Tuple2::_2);
}
@Override
public Map> groupBy(Function super Tuple2, ? extends C> classifier) {
Objects.requireNonNull(classifier, "classifier is null");
return foldLeft(HashMap.empty(), (map, entry) -> {
final C key = classifier.apply(entry);
final TreeMap values = map.get(key).map(entries -> entries.put(entry._1, entry._2)).getOrElse(
createTreeMap(entries.comparator(), Iterator.of(entry)));
return map.put(key, values);
});
}
@Override
public Iterator> grouped(long size) {
return sliding(size, size);
}
@Override
public boolean hasDefiniteSize() {
return true;
}
@Override
public Tuple2 head() {
if (isEmpty()) {
throw new NoSuchElementException("head of empty TreeMap");
} else {
return entries.min().get();
}
}
@Override
public Option> headOption() {
return isEmpty() ? Option.none() : Option.some(head());
}
@Override
public TreeMap init() {
if (isEmpty()) {
throw new UnsupportedOperationException("init of empty TreeMap");
} else {
final Tuple2 max = entries.max().get();
return new TreeMap<>(entries.delete(max));
}
}
@Override
public Option> initOption() {
return isEmpty() ? Option.none() : Option.some(init());
}
@Override
public boolean isEmpty() {
return entries.isEmpty();
}
@Override
public boolean isTraversableAgain() {
return true;
}
@Override
public Iterator> iterator() {
return entries.iterator();
}
@SuppressWarnings("unchecked")
@Override
public Comparator keyComparator() {
return ((EntryComparator) entries.comparator()).keyComparator;
}
@Override
public SortedSet keySet() {
return TreeSet.ofAll(keyComparator(), iterator().map(Tuple2::_1));
}
@Override
public TreeMap map(BiFunction super K, ? super V, Tuple2> mapper) {
return map(naturalComparator(), mapper);
}
@Override
public TreeMap map(Comparator super K2> keyComparator,
BiFunction super K, ? super V, Tuple2> mapper) {
Objects.requireNonNull(mapper, "mapper is null");
return createTreeMap(new EntryComparator<>(keyComparator),
entries.iterator().map(entry -> mapper.apply(entry._1, entry._2)));
}
@Override
public TreeMap mapValues(Function super V, ? extends W> valueMapper) {
Objects.requireNonNull(valueMapper, "valueMapper is null");
return map(keyComparator(), (k, v) -> Tuple.of(k, valueMapper.apply(v)));
}
@Override
public Match.MatchValue.Of> match() {
return Match.of(this);
}
@Override
public Option> max() {
return entries.max();
}
@Override
public TreeMap merge(Map extends K, ? extends V> that) {
return (TreeMap) Collections.mergeMaps(this, that, m -> createTreeMap(entries.comparator(), that));
}
@Override
public TreeMap merge(Map extends K, U> that,
BiFunction super V, ? super U, ? extends V> collisionResolution) {
return (TreeMap) Collections.mergeMaps(this, that, m -> createTreeMap(entries.comparator(), that), collisionResolution);
}
@Override
public Option> min() {
return entries.min();
}
@Override
public Tuple2, TreeMap> partition(Predicate super Tuple2> predicate) {
Objects.requireNonNull(predicate, "predicate is null");
final Tuple2>, Iterator>> p = iterator().partition(predicate);
final TreeMap treeMap1 = createTreeMap(entries.comparator(), p._1);
final TreeMap treeMap2 = createTreeMap(entries.comparator(), p._2);
return Tuple.of(treeMap1, treeMap2);
}
@Override
public TreeMap peek(Consumer super Tuple2> action) {
Objects.requireNonNull(action, "action is null");
if (!isEmpty()) {
action.accept(entries.min().get());
}
return this;
}
@Override
public TreeMap put(K key, V value) {
return new TreeMap<>(entries.insert(new Tuple2<>(key, value)));
}
@SuppressWarnings("unchecked")
@Override
public TreeMap put(Tuple2 extends K, ? extends V> entry) {
Objects.requireNonNull(entry, "entry is null");
return new TreeMap<>(entries.insert((Tuple2) entry));
}
@Override
public TreeMap remove(K key) {
final V ignored = null;
final Tuple2 entry = new Tuple2<>(key, ignored);
if (entries.contains(entry)) {
return new TreeMap<>(entries.delete(entry));
} else {
return this;
}
}
@Override
public TreeMap removeAll(Iterable extends K> keys) {
final V ignored = null;
RedBlackTree> removed = entries;
for (K key : keys) {
final Tuple2 entry = new Tuple2<>(key, ignored);
if (removed.contains(entry)) {
removed = removed.delete(entry);
}
}
if (removed.size() == entries.size()) {
return this;
} else {
return new TreeMap<>(removed);
}
}
@Override
public TreeMap replace(Tuple2 currentElement, Tuple2 newElement) {
Objects.requireNonNull(currentElement, "currentElement is null");
Objects.requireNonNull(newElement, "newElement is null");
return containsKey(currentElement._1) ? remove(currentElement._1).put(newElement) : this;
}
@Override
public TreeMap replaceAll(Tuple2 currentElement, Tuple2 newElement) {
return replace(currentElement, newElement);
}
@Override
public TreeMap retainAll(Iterable extends Tuple2> elements) {
Objects.requireNonNull(elements, "elements is null");
RedBlackTree> tree = RedBlackTree.empty(entries.comparator());
for (Tuple2 entry : elements) {
if (contains(entry)) {
tree = tree.insert(entry);
}
}
return new TreeMap<>(tree);
}
@Override
public TreeMap scan(Tuple2 zero, BiFunction super Tuple2, ? super Tuple2, ? extends Tuple2> operation) {
Objects.requireNonNull(operation, "operation is null");
return Collections.scanLeft(this, zero, operation, TreeMap.empty(keyComparator()), TreeMap::put, Function.identity());
}
@Override
public Seq scanLeft(U zero, BiFunction super U, ? super Tuple2, ? extends U> operation) {
Objects.requireNonNull(operation, "operation is null");
return Collections.scanLeft(this, zero, operation, List.empty(), List::prepend, List::reverse);
}
@Override
public Seq scanRight(U zero, BiFunction super Tuple2, ? super U, ? extends U> operation) {
Objects.requireNonNull(operation, "operation is null");
return Collections.scanRight(this, zero, operation, List.empty(), List::prepend, Function.identity());
}
@Override
public int size() {
return entries.size();
}
@Override
public Iterator> sliding(long size) {
return sliding(size, 1);
}
@Override
public Iterator> sliding(long size, long step) {
return iterator().sliding(size, step).map(seq -> createTreeMap(entries.comparator(), seq));
}
@Override
public Tuple2, TreeMap> span(Predicate super Tuple2> predicate) {
Objects.requireNonNull(predicate, "predicate is null");
final Tuple2>, Iterator>> t = iterator().span(predicate);
final TreeMap treeMap1 = createTreeMap(entries.comparator(), t._1);
final TreeMap treeMap2 = createTreeMap(entries.comparator(), t._2);
return Tuple.of(treeMap1, treeMap2);
}
@Override
public TreeMap tail() {
if (isEmpty()) {
throw new UnsupportedOperationException("tail of empty TreeMap");
} else {
final Tuple2 min = entries.min().get();
return new TreeMap<>(entries.delete(min));
}
}
@Override
public Option> tailOption() {
return isEmpty() ? Option.none() : Option.some(tail());
}
@Override
public TreeMap take(long n) {
return createTreeMap(entries.comparator(), entries.iterator().take(n));
}
@Override
public TreeMap takeRight(long n) {
return createTreeMap(entries.comparator(), entries.iterator().takeRight(n));
}
@Override
public TreeMap takeUntil(Predicate super Tuple2> predicate) {
Objects.requireNonNull(predicate, "predicate is null");
return createTreeMap(entries.comparator(), entries.iterator().takeUntil(predicate));
}
@Override
public TreeMap takeWhile(Predicate super Tuple2> predicate) {
Objects.requireNonNull(predicate, "predicate is null");
return createTreeMap(entries.comparator(), entries.iterator().takeWhile(predicate));
}
@Override
public java.util.TreeMap toJavaMap() {
return toJavaMap(() -> new java.util.TreeMap<>(keyComparator()), t -> t);
}
@Override
public Seq values() {
return iterator().map(Tuple2::_2).toStream();
}
/**
* Internal factory method, used with Tuple2 comparator instead of a key comparator.
*
* @param comparator An Tuple2 comparator
* @param entries Map entries
* @param Key type
* @param Value type
* @return A new TreeMap.
*/
@SuppressWarnings("unchecked")
private static TreeMap createTreeMap(Comparator super Tuple2> comparator,
Iterable extends Tuple2 extends K, ? extends V>> entries) {
RedBlackTree> tree = RedBlackTree.empty(comparator);
for (Tuple2 extends K, ? extends V> entry : entries) {
tree = tree.insert((Tuple2) entry);
}
return new TreeMap<>(tree);
}
// -- Object
@Override
public boolean equals(Object o) {
if (o == this) {
return true;
} else if (o instanceof TreeMap) {
final TreeMap, ?> that = (TreeMap, ?>) o;
return entries.equals(that.entries);
} else {
return false;
}
}
@Override
public int hashCode() {
return entries.hashCode();
}
@Override
public String stringPrefix() {
return "TreeMap";
}
@Override
public String toString() {
return mkString(stringPrefix() + "(", ", ", ")");
}
/**
* Used to compare entries by key and store the keyComparator for later access.
*
* @param key type
* @param value type, needed at compile time for the Comparator interface
*/
static class EntryComparator implements Comparator>, Serializable {
private static final long serialVersionUID = 1L;
final Comparator keyComparator;
@SuppressWarnings("unchecked")
EntryComparator(Comparator super K> keyComparator) {
this.keyComparator = (Comparator) keyComparator;
}
@Override
public int compare(Tuple2 e1, Tuple2 e2) {
return keyComparator.compare(e1._1, e2._1);
}
}
}