com.github.andrewoma.dexx.collection.TreeMap Maven / Gradle / Ivy
/*
* Copyright (c) 2014 Andrew O'Malley
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.github.andrewoma.dexx.collection;
import com.github.andrewoma.dexx.collection.internal.base.AbstractIterable;
import com.github.andrewoma.dexx.collection.internal.base.AbstractSortedMap;
import com.github.andrewoma.dexx.collection.internal.builder.AbstractSelfBuilder;
import com.github.andrewoma.dexx.collection.internal.redblack.DefaultTreeFactory;
import com.github.andrewoma.dexx.collection.internal.redblack.DerivedKeyFactory;
import com.github.andrewoma.dexx.collection.internal.redblack.RedBlackTree;
import com.github.andrewoma.dexx.collection.internal.redblack.Tree;
import com.github.andrewoma.dexx.collection.internal.redblack.TreeFactory;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Comparator;
import java.util.Iterator;
import java.util.NoSuchElementException;
/**
* {@code TreeMap} is an implementation of {@code SortedMap} based on a
* red-black tree.
*
* {@code TreeMaps} can be constructed with a {@link com.github.andrewoma.dexx.collection.KeyFunction}
* to provide modest memory saving per node. See {@link com.github.andrewoma.dexx.collection.DerivedKeyHashMap}
* for an example of using a key function.
*/
public class TreeMap extends AbstractSortedMap {
private Tree tree;
private final RedBlackTree redBlackTree;
public TreeMap() {
redBlackTree = new RedBlackTree();
}
@NotNull
public static BuilderFactory, TreeMap> factory(final Comparator super K> ordering, final KeyFunction keyFunction) {
return new BuilderFactory, TreeMap>() {
@NotNull
@Override
public Builder, TreeMap> newBuilder() {
return new AbstractSelfBuilder, TreeMap>(new TreeMap(ordering, keyFunction)) {
@NotNull
@Override
public Builder, TreeMap> add(Pair element) {
result = result.put(element.component1(), element.component2());
return this;
}
};
}
};
}
@Override
public Comparator super K> comparator() {
return redBlackTree.getOrdering();
}
public TreeMap(Comparator super K> ordering, KeyFunction keyFunction) {
TreeFactory factory = keyFunction == null ? new DefaultTreeFactory() : new DerivedKeyFactory();
redBlackTree = new RedBlackTree(factory, ordering, keyFunction);
}
private TreeMap(Tree tree, RedBlackTree redBlackTree) {
this.tree = tree;
this.redBlackTree = redBlackTree;
}
@Override
public boolean containsKey(@NotNull K key) {
return redBlackTree.contains(tree, key);
}
@NotNull
@Override
public TreeMap put(@NotNull K key, V value) {
return new TreeMap(redBlackTree.update(tree, key, value, true), redBlackTree);
}
@Override
public V get(@NotNull K key) {
return redBlackTree.get(tree, key);
}
@Override
public int size() {
return RedBlackTree.count(tree);
}
@Override
public boolean isEmpty() {
return redBlackTree.isEmpty(tree);
}
@NotNull
@Override
public TreeMap remove(@NotNull K key) {
return new TreeMap(redBlackTree.delete(tree, key), redBlackTree);
}
@NotNull
@Override
public Iterator> iterator() {
return redBlackTree.iterator(tree);
}
public void forEach(@NotNull Function, U> f) {
redBlackTree.forEach(tree, f);
}
@Nullable
@Override
public Pair first() {
try {
return toPair(redBlackTree.smallest(tree));
} catch (NoSuchElementException e) {
return null;
}
}
private Pair toPair(Tree tree) {
return new Pair(tree.getKey(redBlackTree.getKeyFunction()), tree.getValue());
}
@Nullable
@Override
public Pair last() {
try {
return toPair(redBlackTree.greatest(tree));
} catch (NoSuchElementException e) {
return null;
}
}
@NotNull
@Override
public SortedMap drop(int number) {
return new TreeMap(redBlackTree.drop(tree, number), redBlackTree);
}
@NotNull
@Override
public SortedMap take(int number) {
return new TreeMap(redBlackTree.take(tree, number), redBlackTree);
}
@NotNull
@Override
public SortedMap from(@NotNull K key, boolean inclusive) {
return new TreeMap(redBlackTree.from(tree, key, inclusive), redBlackTree);
}
@NotNull
@Override
public SortedMap to(@NotNull K key, boolean inclusive) {
return new TreeMap(redBlackTree.until(tree, key, inclusive), redBlackTree);
}
@NotNull
@Override
public SortedMap range(@NotNull K from, boolean fromInclusive, @NotNull K to, boolean toInclusive) {
return new TreeMap(redBlackTree.range(tree, from, fromInclusive, to, toInclusive), redBlackTree);
}
@NotNull
@Override
public Iterable keys() {
return new AbstractIterable() {
@NotNull
@Override
public Iterator iterator() {
return redBlackTree.keysIterator(tree);
}
};
}
@NotNull
@Override
public Iterable values() {
return new AbstractIterable() {
@NotNull
@Override
public Iterator iterator() {
return redBlackTree.valuesIterator(tree);
}
};
}
@NotNull
protected TreeMap slice(int from, int until) {
return new TreeMap(redBlackTree.slice(tree, from, until), redBlackTree);
}
}