All Downloads are FREE. Search and download functionalities are using the official Maven repository.

javaslang.collection.TreeSet Maven / Gradle / Ivy

There is a newer version: 8.1.2
Show newest version
/*     / \____  _    _  ____   ______  / \ ____  __    _______
 *    /  /    \/ \  / \/    \ /  /\__\/  //    \/  \  //  /\__\   JΛVΛSLΛNG
 *  _/  /  /\  \  \/  /  /\  \\__\\  \  //  /\  \ /\\/ \ /__\ \   Copyright 2014-2016 Javaslang, http://javaslang.io
 * /___/\_/  \_/\____/\_/  \_/\__\/__/\__\_/  \_//  \__/\_____/   Licensed under the Apache License, Version 2.0
 */
package javaslang.collection;

import javaslang.*;
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;

/**
 * SortedSet implementation, backed by a Red/Black Tree.
 *
 * @param  Component type
 * @author Daniel Dietrich
 * @since 2.0.0
 */
// DEV-NOTE: it is not possible to create an EMPTY TreeSet without a Comparator type in scope
public final class TreeSet implements Kind1, T>, SortedSet, Serializable {

    private static final long serialVersionUID = 1L;

    private final RedBlackTree tree;

    TreeSet(RedBlackTree tree) {
        this.tree = tree;
    }

    /**
     * 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.TreeSet}.
     *
     * @param  Component type of the List.
     * @return A javaslang.collection.List Collector.
     */
    public static  Collector, TreeSet> collector() {
        final Supplier> supplier = ArrayList::new;
        final BiConsumer, T> accumulator = ArrayList::add;
        final BinaryOperator> combiner = (left, right) -> {
            left.addAll(right);
            return left;
        };
        final Function, TreeSet> finisher = list -> TreeSet.ofAll(naturalComparator(), list);
        return Collector.of(supplier, accumulator, combiner, finisher);
    }

    public static > TreeSet empty() {
        return new TreeSet<>(RedBlackTree. empty());
    }

    public static  TreeSet empty(Comparator comparator) {
        Objects.requireNonNull(comparator, "comparator is null");
        return new TreeSet<>(RedBlackTree.empty(comparator));
    }

    /**
     * Narrows a widened {@code TreeSet} to {@code TreeSet}
     * by performing a type safe-cast. This is eligible because immutable/read-only
     * collections are covariant.
     * 

* CAUTION: The underlying {@code Comparator} might fail! * * @param treeSet A {@code TreeSet}. * @param Component type of the {@code TreeSet}. * @return the given {@code treeSet} instance as narrowed type {@code TreeSet}. */ @SuppressWarnings("unchecked") public static TreeSet narrow(TreeSet treeSet) { return (TreeSet) treeSet; } public static > TreeSet of(T value) { return new TreeSet<>(RedBlackTree.of(value)); } public static TreeSet of(Comparator comparator, T value) { Objects.requireNonNull(comparator, "comparator is null"); return new TreeSet<>(RedBlackTree.of(comparator, value)); } @SuppressWarnings("varargs") @SafeVarargs public static > TreeSet of(T... values) { Objects.requireNonNull(values, "values is null"); return new TreeSet<>(RedBlackTree.of(values)); } @SuppressWarnings("varargs") @SafeVarargs public static TreeSet of(Comparator comparator, T... values) { Objects.requireNonNull(comparator, "comparator is null"); Objects.requireNonNull(values, "values is null"); return new TreeSet<>(RedBlackTree.of(comparator, values)); } /** * Returns a TreeSet containing {@code n} values of a given Function {@code f} * over a range of integer values from 0 to {@code n - 1}. * * @param Component type of the TreeSet * @param comparator The comparator used to sort the elements * @param n The number of elements in the TreeSet * @param f The Function computing element values * @return A TreeSet consisting of elements {@code f(0),f(1), ..., f(n - 1)} * @throws NullPointerException if {@code comparator} or {@code f} are null */ public static TreeSet tabulate(Comparator comparator, int n, Function f) { Objects.requireNonNull(comparator, "comparator is null"); Objects.requireNonNull(f, "f is null"); return Collections.tabulate(n, f, TreeSet.empty(comparator), values -> TreeSet.of(comparator, values)); } /** * Returns a TreeSet containing {@code n} values of a given Function {@code f} * over a range of integer values from 0 to {@code n - 1}. * The underlying comparator is the natural comparator of T. * * @param Component type of the TreeSet * @param n The number of elements in the TreeSet * @param f The Function computing element values * @return A TreeSet consisting of elements {@code f(0),f(1), ..., f(n - 1)} * @throws NullPointerException if {@code f} is null */ public static > TreeSet tabulate(int n, Function f) { Objects.requireNonNull(f, "f is null"); return tabulate((Comparator & Serializable) T::compareTo, n, f); } /** * Returns a TreeSet containing {@code n} values supplied by a given Supplier {@code s}. * * @param Component type of the TreeSet * @param comparator The comparator used to sort the elements * @param n The number of elements in the TreeSet * @param s The Supplier computing element values * @return A TreeSet of size {@code n}, where each element contains the result supplied by {@code s}. * @throws NullPointerException if {@code comparator} or {@code s} are null */ public static TreeSet fill(Comparator comparator, int n, Supplier s) { Objects.requireNonNull(comparator, "comparator is null"); Objects.requireNonNull(s, "s is null"); return Collections.fill(n, s, TreeSet.empty(comparator), values -> TreeSet.of(comparator, values)); } /** * Returns a TreeSet containing {@code n} values supplied by a given Supplier {@code s}. * The underlying comparator is the natural comparator of T. * * @param Component type of the TreeSet * @param n The number of elements in the TreeSet * @param s The Supplier computing element values * @return A TreeSet of size {@code n}, where each element contains the result supplied by {@code s}. * @throws NullPointerException if {@code s} is null */ public static > TreeSet fill(int n, Supplier s) { Objects.requireNonNull(s, "s is null"); return fill((Comparator & Serializable) T::compareTo, n, s); } public static > TreeSet ofAll(Iterable values) { Objects.requireNonNull(values, "values is null"); return values.iterator().hasNext() ? new TreeSet<>(RedBlackTree.ofAll(values)) : empty(); } @SuppressWarnings("unchecked") public static TreeSet ofAll(Comparator comparator, Iterable values) { Objects.requireNonNull(comparator, "comparator is null"); Objects.requireNonNull(values, "values is null"); return values.iterator().hasNext() ? new TreeSet<>(RedBlackTree.ofAll(comparator, values)) : (TreeSet) empty(); } /** * Creates a TreeSet based on the elements of a boolean array. * * @param array a boolean array * @return A new TreeSet of Boolean values */ public static TreeSet ofAll(boolean[] array) { Objects.requireNonNull(array, "array is null"); return TreeSet.ofAll(Iterator.ofAll(array)); } /** * Creates a TreeSet based on the elements of a byte array. * * @param array a byte array * @return A new TreeSet of Byte values */ public static TreeSet ofAll(byte[] array) { Objects.requireNonNull(array, "array is null"); return TreeSet.ofAll(Iterator.ofAll(array)); } /** * Creates a TreeSet based on the elements of a char array. * * @param array a char array * @return A new TreeSet of Character values */ public static TreeSet ofAll(char[] array) { Objects.requireNonNull(array, "array is null"); return TreeSet.ofAll(Iterator.ofAll(array)); } /** * Creates a TreeSet based on the elements of a double array. * * @param array a double array * @return A new TreeSet of Double values */ public static TreeSet ofAll(double[] array) { Objects.requireNonNull(array, "array is null"); return TreeSet.ofAll(Iterator.ofAll(array)); } /** * Creates a TreeSet based on the elements of a float array. * * @param array a float array * @return A new TreeSet of Float values */ public static TreeSet ofAll(float[] array) { Objects.requireNonNull(array, "array is null"); return TreeSet.ofAll(Iterator.ofAll(array)); } /** * Creates a TreeSet based on the elements of an int array. * * @param array an int array * @return A new TreeSet of Integer values */ public static TreeSet ofAll(int[] array) { Objects.requireNonNull(array, "array is null"); return TreeSet.ofAll(Iterator.ofAll(array)); } /** * Creates a TreeSet based on the elements of a long array. * * @param array a long array * @return A new TreeSet of Long values */ public static TreeSet ofAll(long[] array) { Objects.requireNonNull(array, "array is null"); return TreeSet.ofAll(Iterator.ofAll(array)); } /** * Creates a TreeSet based on the elements of a short array. * * @param array a short array * @return A new TreeSet of Short values */ public static TreeSet ofAll(short[] array) { Objects.requireNonNull(array, "array is null"); return TreeSet.ofAll(Iterator.ofAll(array)); } /** * Creates a TreeSet of int numbers starting from {@code from}, extending to {@code toExclusive - 1}. *

* Examples: *

     * 
     * TreeSet.range(0, 0)  // = TreeSet()
     * TreeSet.range(2, 0)  // = TreeSet()
     * TreeSet.range(-2, 2) // = TreeSet(-2, -1, 0, 1)
     * 
     * 
* * @param from the first number * @param toExclusive the last number + 1 * @return a range of int values as specified or the empty range if {@code from >= toExclusive} */ public static TreeSet range(int from, int toExclusive) { return TreeSet.ofAll(Iterator.range(from, toExclusive)); } public static TreeSet range(char from, char toExclusive) { return TreeSet.ofAll(Iterator.range(from, toExclusive)); } /** * Creates a TreeSet of int numbers starting from {@code from}, extending to {@code toExclusive - 1}, * with {@code step}. *

* Examples: *

     * 
     * TreeSet.rangeBy(1, 3, 1)  // = TreeSet(1, 2)
     * TreeSet.rangeBy(1, 4, 2)  // = TreeSet(1, 3)
     * TreeSet.rangeBy(4, 1, -2) // = TreeSet(4, 2)
     * TreeSet.rangeBy(4, 1, 2)  // = TreeSet()
     * 
     * 
* * @param from the first number * @param toExclusive the last number + 1 * @param step the step * @return a range of long values as specified or the empty range if
* {@code from >= toInclusive} and {@code step > 0} or
* {@code from <= toInclusive} and {@code step < 0} * @throws IllegalArgumentException if {@code step} is zero */ public static TreeSet rangeBy(int from, int toExclusive, int step) { return TreeSet.ofAll(Iterator.rangeBy(from, toExclusive, step)); } public static TreeSet rangeBy(char from, char toExclusive, int step) { return TreeSet.ofAll(Iterator.rangeBy(from, toExclusive, step)); } public static TreeSet rangeBy(double from, double toExclusive, double step) { return TreeSet.ofAll(Iterator.rangeBy(from, toExclusive, step)); } /** * Creates a TreeSet of long numbers starting from {@code from}, extending to {@code toExclusive - 1}. *

* Examples: *

     * 
     * TreeSet.range(0L, 0L)  // = TreeSet()
     * TreeSet.range(2L, 0L)  // = TreeSet()
     * TreeSet.range(-2L, 2L) // = TreeSet(-2L, -1L, 0L, 1L)
     * 
     * 
* * @param from the first number * @param toExclusive the last number + 1 * @return a range of long values as specified or the empty range if {@code from >= toExclusive} */ public static TreeSet range(long from, long toExclusive) { return TreeSet.ofAll(Iterator.range(from, toExclusive)); } /** * Creates a TreeSet of long numbers starting from {@code from}, extending to {@code toExclusive - 1}, * with {@code step}. *

* Examples: *

     * 
     * TreeSet.rangeBy(1L, 3L, 1L)  // = TreeSet(1L, 2L)
     * TreeSet.rangeBy(1L, 4L, 2L)  // = TreeSet(1L, 3L)
     * TreeSet.rangeBy(4L, 1L, -2L) // = TreeSet(4L, 2L)
     * TreeSet.rangeBy(4L, 1L, 2L)  // = TreeSet()
     * 
     * 
* * @param from the first number * @param toExclusive the last number + 1 * @param step the step * @return a range of long values as specified or the empty range if
* {@code from >= toInclusive} and {@code step > 0} or
* {@code from <= toInclusive} and {@code step < 0} * @throws IllegalArgumentException if {@code step} is zero */ public static TreeSet rangeBy(long from, long toExclusive, long step) { return TreeSet.ofAll(Iterator.rangeBy(from, toExclusive, step)); } /** * Creates a TreeSet of int numbers starting from {@code from}, extending to {@code toInclusive}. *

* Examples: *

     * 
     * TreeSet.rangeClosed(0, 0)  // = TreeSet(0)
     * TreeSet.rangeClosed(2, 0)  // = TreeSet()
     * TreeSet.rangeClosed(-2, 2) // = TreeSet(-2, -1, 0, 1, 2)
     * 
     * 
* * @param from the first number * @param toInclusive the last number * @return a range of int values as specified or the empty range if {@code from > toInclusive} */ public static TreeSet rangeClosed(int from, int toInclusive) { return TreeSet.ofAll(Iterator.rangeClosed(from, toInclusive)); } public static TreeSet rangeClosed(char from, char toInclusive) { return TreeSet.ofAll(Iterator.rangeClosed(from, toInclusive)); } /** * Creates a TreeSet of int numbers starting from {@code from}, extending to {@code toInclusive}, * with {@code step}. *

* Examples: *

     * 
     * TreeSet.rangeClosedBy(1, 3, 1)  // = TreeSet(1, 2, 3)
     * TreeSet.rangeClosedBy(1, 4, 2)  // = TreeSet(1, 3)
     * TreeSet.rangeClosedBy(4, 1, -2) // = TreeSet(4, 2)
     * TreeSet.rangeClosedBy(4, 1, 2)  // = TreeSet()
     * 
     * 
* * @param from the first number * @param toInclusive the last number * @param step the step * @return a range of int values as specified or the empty range if
* {@code from > toInclusive} and {@code step > 0} or
* {@code from < toInclusive} and {@code step < 0} * @throws IllegalArgumentException if {@code step} is zero */ public static TreeSet rangeClosedBy(int from, int toInclusive, int step) { return TreeSet.ofAll(Iterator.rangeClosedBy(from, toInclusive, step)); } public static TreeSet rangeClosedBy(char from, char toInclusive, int step) { return TreeSet.ofAll(Iterator.rangeClosedBy(from, toInclusive, step)); } public static TreeSet rangeClosedBy(double from, double toInclusive, double step) { return TreeSet.ofAll(Iterator.rangeClosedBy(from, toInclusive, step)); } /** * Creates a TreeSet of long numbers starting from {@code from}, extending to {@code toInclusive}. *

* Examples: *

     * 
     * TreeSet.rangeClosed(0L, 0L)  // = TreeSet(0L)
     * TreeSet.rangeClosed(2L, 0L)  // = TreeSet()
     * TreeSet.rangeClosed(-2L, 2L) // = TreeSet(-2L, -1L, 0L, 1L, 2L)
     * 
     * 
* * @param from the first number * @param toInclusive the last number * @return a range of long values as specified or the empty range if {@code from > toInclusive} */ public static TreeSet rangeClosed(long from, long toInclusive) { return TreeSet.ofAll(Iterator.rangeClosed(from, toInclusive)); } /** * Creates a TreeSet of long numbers starting from {@code from}, extending to {@code toInclusive}, * with {@code step}. *

* Examples: *

     * 
     * TreeSet.rangeClosedBy(1L, 3L, 1L)  // = TreeSet(1L, 2L, 3L)
     * TreeSet.rangeClosedBy(1L, 4L, 2L)  // = TreeSet(1L, 3L)
     * TreeSet.rangeClosedBy(4L, 1L, -2L) // = TreeSet(4L, 2L)
     * TreeSet.rangeClosedBy(4L, 1L, 2L)  // = TreeSet()
     * 
     * 
* * @param from the first number * @param toInclusive the last number * @param step the step * @return a range of int values as specified or the empty range if
* {@code from > toInclusive} and {@code step > 0} or
* {@code from < toInclusive} and {@code step < 0} * @throws IllegalArgumentException if {@code step} is zero */ public static TreeSet rangeClosedBy(long from, long toInclusive, long step) { return TreeSet.ofAll(Iterator.rangeClosedBy(from, toInclusive, step)); } @Override public TreeSet add(T element) { return new TreeSet<>(tree.insert(element)); } @Override public TreeSet addAll(Iterable elements) { Objects.requireNonNull(elements, "elements is null"); RedBlackTree that = tree; for (T element : elements) { that = that.insert(element); } if (tree == that) { return this; } else { return new TreeSet<>(that); } } @Override public Comparator comparator() { return tree.comparator(); } @SuppressWarnings("unchecked") @Override public TreeSet diff(Set elements) { Objects.requireNonNull(elements, "elements is null"); if (elements instanceof TreeSet) { final RedBlackTree that = ((TreeSet) elements).tree; return new TreeSet<>(tree.difference(that)); } else { return removeAll(elements); } } @Override public boolean contains(T element) { return tree.contains(element); } @Override public TreeSet distinct() { return this; } @Override public TreeSet distinctBy(Comparator comparator) { Objects.requireNonNull(comparator, "comparator is null"); return TreeSet.ofAll(tree.comparator(), iterator().distinctBy(comparator)); } @Override public TreeSet distinctBy(Function keyExtractor) { Objects.requireNonNull(keyExtractor, "keyExtractor is null"); return TreeSet.ofAll(tree.comparator(), iterator().distinctBy(keyExtractor)); } @Override public TreeSet drop(long n) { if (n <= 0) { return this; } else if (n >= length()) { return empty(tree.comparator()); } else { return TreeSet.ofAll(tree.comparator(), iterator().drop(n)); } } @Override public TreeSet dropRight(long n) { if (n <= 0) { return this; } else if (n >= length()) { return empty(tree.comparator()); } else { return TreeSet.ofAll(tree.comparator(), iterator().dropRight(n)); } } @Override public TreeSet dropUntil(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return dropWhile(predicate.negate()); } @Override public TreeSet dropWhile(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); final TreeSet treeSet = TreeSet.ofAll(tree.comparator(), iterator().dropWhile(predicate)); return (treeSet.length() == length()) ? this : treeSet; } @Override public TreeSet filter(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); final TreeSet treeSet = TreeSet.ofAll(tree.comparator(), iterator().filter(predicate)); return (treeSet.length() == length()) ? this : treeSet; } @Override public TreeSet flatMap(Comparator comparator, Function> mapper) { Objects.requireNonNull(mapper, "mapper is null"); return TreeSet.ofAll(comparator, iterator().flatMap(mapper)); } @Override public TreeSet flatMap(Function> mapper) { return flatMap(naturalComparator(), mapper); } @Override public U foldRight(U zero, BiFunction f) { Objects.requireNonNull(f, "f is null"); return iterator().foldRight(zero, f); } @Override public Map> groupBy(Function classifier) { Objects.requireNonNull(classifier, "classifier is null"); return iterator().groupBy(classifier).map( (key, iterator) -> Tuple.of(key, TreeSet.ofAll(tree.comparator(), iterator))); } @Override public Iterator> grouped(long size) { return sliding(size, size); } @Override public boolean hasDefiniteSize() { return true; } @Override public T head() { if (isEmpty()) { throw new NoSuchElementException("head of empty TreeSet"); } else { return tree.min().get(); } } @Override public Option headOption() { return tree.min(); } @Override public TreeSet init() { if (isEmpty()) { throw new UnsupportedOperationException("init of empty TreeSet"); } else { return new TreeSet<>(tree.delete(tree.max().get())); } } @Override public Option> initOption() { return isEmpty() ? Option.none() : Option.some(init()); } @SuppressWarnings("unchecked") @Override public TreeSet intersect(Set elements) { Objects.requireNonNull(elements, "elements is null"); if (elements instanceof TreeSet) { final RedBlackTree that = ((TreeSet) elements).tree; return new TreeSet<>(tree.intersection(that)); } else { return retainAll(elements); } } @Override public boolean isEmpty() { return tree.isEmpty(); } @Override public boolean isTraversableAgain() { return true; } @Override public Iterator iterator() { return tree.iterator(); } @Override public int length() { return tree.size(); } @Override public TreeSet map(Comparator comparator, Function mapper) { Objects.requireNonNull(mapper, "mapper is null"); return TreeSet.ofAll(comparator, iterator().map(mapper)); } @Override public TreeSet map(Function mapper) { return map(naturalComparator(), mapper); } @Override public Option max() { return tree.max(); } @Override public Option min() { return tree.min(); } @Override public Tuple2, TreeSet> partition(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return iterator().partition(predicate).map(i1 -> TreeSet.ofAll(tree.comparator(), i1), i2 -> TreeSet.ofAll(tree.comparator(), i2)); } @Override public TreeSet peek(Consumer action) { Objects.requireNonNull(action, "action is null"); if (!isEmpty()) { action.accept(head()); } return this; } @Override public TreeSet remove(T element) { return new TreeSet<>(tree.delete(element)); } @Override public TreeSet removeAll(Iterable elements) { Objects.requireNonNull(elements, "elements is null"); if (isEmpty()) { return this; } else { RedBlackTree that = tree; final java.util.Iterator iter = elements.iterator(); while (!that.isEmpty() && iter.hasNext()) { that = that.delete(iter.next()); } if (that == tree) { return this; } else { return new TreeSet<>(that); } } } @Override public TreeSet replace(T currentElement, T newElement) { if (tree.contains(currentElement)) { return new TreeSet<>(tree.delete(currentElement).insert(newElement)); } else { return this; } } @Override public TreeSet replaceAll(T currentElement, T newElement) { // a set has only one occurrence return replace(currentElement, newElement); } @Override public TreeSet retainAll(Iterable elements) { Objects.requireNonNull(elements, "elements is null"); if (isEmpty()) { return this; } else { final RedBlackTree kept = RedBlackTree.ofAll(tree.comparator(), elements); final RedBlackTree newTree = tree.intersection(kept); return newTree.size() == tree.size() ? this : new TreeSet<>(tree.intersection(kept)); } } @Override public TreeSet scan(T zero, BiFunction operation) { Objects.requireNonNull(operation, "operation is null"); return Collections.scanLeft(this, zero, operation, TreeSet.empty(comparator()), TreeSet::add, Function.identity()); } @Override public Set scanLeft(U zero, BiFunction operation) { Objects.requireNonNull(operation, "operation is null"); if (zero instanceof Comparable) { final Comparator comparator = naturalComparator(); return Collections.scanLeft(this, zero, operation, TreeSet.empty(comparator), TreeSet::add, Function.identity()); } else { return Collections.scanLeft(this, zero, operation, new java.util.ArrayList<>(), (c, u) -> { c.add(u); return c; }, HashSet::ofAll); } } @Override public Set scanRight(U zero, BiFunction operation) { Objects.requireNonNull(operation, "operation is null"); if (zero instanceof Comparable) { final Comparator comparator = naturalComparator(); return Collections.scanRight(this, zero, operation, TreeSet.empty(comparator), TreeSet::add, Function.identity()); } else { return Collections.scanRight(this, zero, operation, new java.util.ArrayList<>(), (c, u) -> { c.add(u); return c; }, HashSet::ofAll); } } @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 -> TreeSet.ofAll(tree.comparator(), seq)); } @Override public Tuple2, TreeSet> span(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return iterator().span(predicate).map(i1 -> TreeSet.ofAll(tree.comparator(), i1), i2 -> TreeSet.ofAll(tree.comparator(), i2)); } @Override public TreeSet tail() { if (isEmpty()) { throw new UnsupportedOperationException("tail of empty TreeSet"); } else { return new TreeSet<>(tree.delete(tree.min().get())); } } @Override public Option> tailOption() { return isEmpty() ? Option.none() : Option.some(tail()); } @Override public TreeSet take(long n) { if (n <= 0) { return empty(tree.comparator()); } else if (n >= length()) { return this; } else { return TreeSet.ofAll(tree.comparator(), iterator().take(n)); } } @Override public TreeSet takeRight(long n) { if (n <= 0) { return empty(tree.comparator()); } else if (n >= length()) { return this; } else { return TreeSet.ofAll(tree.comparator(), iterator().takeRight(n)); } } @Override public TreeSet takeUntil(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); final TreeSet treeSet = takeWhile(predicate.negate()); return (treeSet.length() == length()) ? this : treeSet; } @Override public TreeSet takeWhile(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); final TreeSet treeSet = TreeSet.ofAll(tree.comparator(), iterator().takeWhile(predicate)); return (treeSet.length() == length()) ? this : treeSet; } /** * Transforms this {@code TreeSet}. * * @param f A transformation * @param Type of transformation result * @return An instance of type {@code U} * @throws NullPointerException if {@code f} is null */ public U transform(Function, ? extends U> f) { Objects.requireNonNull(f, "f is null"); return f.apply(this); } @Override public java.util.TreeSet toJavaSet() { return toJavaSet(() -> new java.util.TreeSet<>(comparator())); } @SuppressWarnings("unchecked") @Override public TreeSet union(Set elements) { Objects.requireNonNull(elements, "elements is null"); if (elements instanceof TreeSet) { final RedBlackTree that = ((TreeSet) elements).tree; return new TreeSet<>(tree.union(that)); } else { return addAll(elements); } } @Override public Tuple2, TreeSet> unzip( Function> unzipper) { Objects.requireNonNull(unzipper, "unzipper is null"); return iterator().unzip(unzipper).map(i1 -> TreeSet.ofAll(naturalComparator(), i1), i2 -> TreeSet.ofAll(naturalComparator(), i2)); } @Override public Tuple3, TreeSet, TreeSet> unzip3( Function> unzipper) { Objects.requireNonNull(unzipper, "unzipper is null"); return iterator().unzip3(unzipper).map( i1 -> TreeSet.ofAll(naturalComparator(), i1), i2 -> TreeSet.ofAll(naturalComparator(), i2), i3 -> TreeSet.ofAll(naturalComparator(), i3)); } @Override public TreeSet> zip(Iterable that) { Objects.requireNonNull(that, "that is null"); final Comparator> tuple2Comparator = Tuple2.comparator(tree.comparator(), naturalComparator()); return TreeSet.ofAll(tuple2Comparator, iterator().zip(that)); } @Override public TreeSet> zipAll(Iterable that, T thisElem, U thatElem) { Objects.requireNonNull(that, "that is null"); final Comparator> tuple2Comparator = Tuple2.comparator(tree.comparator(), naturalComparator()); return TreeSet.ofAll(tuple2Comparator, iterator().zipAll(that, thisElem, thatElem)); } @Override public TreeSet> zipWithIndex() { final Comparator component1Comparator = tree.comparator(); final Comparator> tuple2Comparator = (t1, t2) -> component1Comparator.compare(t1._1, t2._1); return TreeSet.ofAll(tuple2Comparator, iterator().zipWithIndex()); } // -- Object @Override public boolean equals(Object o) { if (o == this) { return true; } else if (o instanceof TreeSet) { final TreeSet that = (TreeSet) o; return tree.equals(that.tree); } else { return false; } } @Override public int hashCode() { return tree.hashCode(); } @Override public String stringPrefix() { return "TreeSet"; } @Override public String toString() { return mkString(stringPrefix() + "(", ", ", ")"); } }