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

io.vavr.collection.TreeSet Maven / Gradle / Ivy

There is a newer version: 1.0.0-alpha-4
Show newest version
/*  __    __  __  __    __  ___
 * \  \  /  /    \  \  /  /  __/
 *  \  \/  /  /\  \  \/  /  /
 *   \____/__/  \__\____/__/
 *
 * Copyright 2014-2019 Vavr, http://vavr.io
 *
 * 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 io.vavr.collection;

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

/**
 * SortedSet implementation, backed by a Red/Black Tree.
 *
 * @param  Component type
 * @author Daniel Dietrich
 */
// DEV-NOTE: it is not possible to create an EMPTY TreeSet without a Comparator type in scope
public final class TreeSet implements 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 TreeSet}.
     * 

* The natural comparator is used to compare TreeSet elements. * * @param Component type of the List. * @return A io.vavr.collection.List Collector. */ public static > Collector, TreeSet> collector() { return collector(Comparators.naturalComparator()); } /** * 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 TreeSet}. * * @param Component type of the List. * @param comparator An element comparator * @return A io.vavr.collection.List Collector. */ public static Collector, TreeSet> collector(Comparator comparator) { Objects.requireNonNull(comparator, "comparator is null"); 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(comparator, list); return Collector.of(supplier, accumulator, combiner, finisher); } public static > TreeSet empty() { return empty(Comparators.naturalComparator()); } 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 of(Comparators.naturalComparator(), 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) { return TreeSet. of(Comparators.naturalComparator(), 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 -> 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(Comparators.naturalComparator(), n, f); } /** * Returns a TreeSet containing tuples returned by {@code n} calls to 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 -> of(comparator, values)); } /** * Returns a TreeSet containing tuples returned by {@code n} calls to 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(Comparators.naturalComparator(), n, s); } public static > TreeSet ofAll(Iterable values) { return ofAll(Comparators.naturalComparator(), values); } @SuppressWarnings("unchecked") public static TreeSet ofAll(Comparator comparator, Iterable values) { Objects.requireNonNull(comparator, "comparator is null"); Objects.requireNonNull(values, "values is null"); if (values instanceof TreeSet && ((TreeSet) values).comparator() == comparator) { return (TreeSet) values; } else { return values.iterator().hasNext() ? new TreeSet<>(RedBlackTree.ofAll(comparator, values)) : empty(comparator); } } public static > TreeSet ofAll(java.util.stream.Stream javaStream) { Objects.requireNonNull(javaStream, "javaStream is null"); return ofAll(Iterator.ofAll(javaStream.iterator())); } public static TreeSet ofAll(Comparator comparator, java.util.stream.Stream javaStream) { Objects.requireNonNull(javaStream, "javaStream is null"); return ofAll(comparator, Iterator.ofAll(javaStream.iterator())); } /** * Creates a TreeSet from boolean values. * * @param elements boolean values * @return A new TreeSet of Boolean values * @throws NullPointerException if elements is null */ public static TreeSet ofAll(boolean... elements) { Objects.requireNonNull(elements, "elements is null"); return TreeSet.ofAll(Iterator.ofAll(elements)); } /** * Creates a TreeSet from byte values. * * @param elements byte values * @return A new TreeSet of Byte values * @throws NullPointerException if elements is null */ public static TreeSet ofAll(byte... elements) { Objects.requireNonNull(elements, "elements is null"); return TreeSet.ofAll(Iterator.ofAll(elements)); } /** * Creates a TreeSet from char values. * * @param elements char values * @return A new TreeSet of Character values * @throws NullPointerException if elements is null */ public static TreeSet ofAll(char... elements) { Objects.requireNonNull(elements, "elements is null"); return TreeSet.ofAll(Iterator.ofAll(elements)); } /** * Creates a TreeSet from double values. * * @param elements double values * @return A new TreeSet of Double values * @throws NullPointerException if elements is null */ public static TreeSet ofAll(double... elements) { Objects.requireNonNull(elements, "elements is null"); return TreeSet.ofAll(Iterator.ofAll(elements)); } /** * Creates a TreeSet from float values. * * @param elements float values * @return A new TreeSet of Float values * @throws NullPointerException if elements is null */ public static TreeSet ofAll(float... elements) { Objects.requireNonNull(elements, "elements is null"); return TreeSet.ofAll(Iterator.ofAll(elements)); } /** * Creates a TreeSet from int values. * * @param elements int values * @return A new TreeSet of Integer values * @throws NullPointerException if elements is null */ public static TreeSet ofAll(int... elements) { Objects.requireNonNull(elements, "elements is null"); return TreeSet.ofAll(Iterator.ofAll(elements)); } /** * Creates a TreeSet from long values. * * @param elements long values * @return A new TreeSet of Long values * @throws NullPointerException if elements is null */ public static TreeSet ofAll(long... elements) { Objects.requireNonNull(elements, "elements is null"); return TreeSet.ofAll(Iterator.ofAll(elements)); } /** * Creates a TreeSet from short values. * * @param elements short values * @return A new TreeSet of Short values * @throws NullPointerException if elements is null */ public static TreeSet ofAll(short... elements) { Objects.requireNonNull(elements, "elements is null"); return TreeSet.ofAll(Iterator.ofAll(elements)); } /** * 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)); } @GwtIncompatible 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)); } @GwtIncompatible 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 contains(element) ? this : new TreeSet<>(tree.insert(element)); } @Override public TreeSet addAll(Iterable elements) { Objects.requireNonNull(elements, "elements is null"); RedBlackTree that = tree; for (T element : elements) { if (!that.contains(element)) { that = that.insert(element); } } if (tree == that) { return this; } else { return new TreeSet<>(that); } } @Override public TreeSet collect(PartialFunction partialFunction) { return ofAll(Comparators.naturalComparator(), iterator(). collect(partialFunction)); } @Override public Comparator comparator() { return tree.comparator(); } @SuppressWarnings("unchecked") @Override public TreeSet diff(Set elements) { Objects.requireNonNull(elements, "elements is null"); if (isEmpty()) { return this; } else if (elements instanceof TreeSet) { final TreeSet that = (TreeSet) elements; return that.isEmpty() ? this : new TreeSet<>(tree.difference(that.tree)); } 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 isEmpty() ? this : TreeSet.ofAll(tree.comparator(), iterator().distinctBy(comparator)); } @Override public TreeSet distinctBy(Function keyExtractor) { Objects.requireNonNull(keyExtractor, "keyExtractor is null"); return isEmpty() ? this : TreeSet.ofAll(tree.comparator(), iterator().distinctBy(keyExtractor)); } @Override public TreeSet drop(int n) { if (n <= 0 || isEmpty()) { return this; } else if (n >= length()) { return empty(tree.comparator()); } else { return TreeSet.ofAll(tree.comparator(), iterator().drop(n)); } } @Override public TreeSet dropRight(int n) { if (n <= 0 || isEmpty()) { 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 reject(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return filter(predicate.negate()); } @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(Comparators.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) { return Collections.groupBy(this, classifier, elements -> ofAll(comparator(), elements)); } @Override public Iterator> grouped(int 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 (isEmpty()) { return this; } else if (elements instanceof TreeSet) { final TreeSet that = (TreeSet) elements; return new TreeSet<>(tree.intersection(that.tree)); } else { return retainAll(elements); } } /** * A {@code TreeSet} is computed synchronously. * * @return false */ @Override public boolean isAsync() { return false; } @Override public boolean isEmpty() { return tree.isEmpty(); } /** * A {@code TreeSet} is computed eagerly. * * @return false */ @Override public boolean isLazy() { return false; } @Override public boolean isTraversableAgain() { return true; } @Override public Iterator iterator() { return tree.iterator(); } @Override public T last() { if (isEmpty()) { throw new NoSuchElementException("last of empty TreeSet"); } else { return tree.max().get(); } } @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(Comparators.naturalComparator(), mapper); } /** * Returns this {@code TreeSet} if it is nonempty, * otherwise {@code TreeSet} created from iterable, using existing comparator. * * @param other An alternative {@code Traversable} * @return this {@code TreeSet} if it is nonempty, * otherwise {@code TreeSet} created from iterable, using existing comparator. */ @Override public TreeSet orElse(Iterable other) { return isEmpty() ? ofAll(tree.comparator(), other) : this; } /** * Returns this {@code TreeSet} if it is nonempty, * otherwise {@code TreeSet} created from result of evaluating supplier, using existing comparator. * * @param supplier An alternative {@code Traversable} * @return this {@code TreeSet} if it is nonempty, * otherwise {@code TreeSet} created from result of evaluating supplier, using existing comparator. */ @Override public TreeSet orElse(Supplier> supplier) { return isEmpty() ? ofAll(tree.comparator(), supplier.get()) : this; } @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) { return Collections.removeAll(this, elements); } @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) { return Collections.retainAll(this, elements); } @Override public TreeSet scan(T zero, BiFunction operation) { return Collections.scanLeft(this, zero, operation, iter -> TreeSet.ofAll(comparator(), iter)); } @Override public Set scanLeft(U zero, BiFunction operation) { if (zero instanceof Comparable) { final Comparator comparator = Comparators.naturalComparator(); return Collections.scanLeft(this, zero, operation, iter -> TreeSet.ofAll(comparator, iter)); } else { return Collections.scanLeft(this, zero, operation, HashSet::ofAll); } } @Override public Set scanRight(U zero, BiFunction operation) { if (zero instanceof Comparable) { final Comparator comparator = Comparators.naturalComparator(); return Collections.scanRight(this, zero, operation, iter -> TreeSet.ofAll(comparator, iter)); } else { return Collections.scanRight(this, zero, operation, HashSet::ofAll); } } @Override public Iterator> slideBy(Function classifier) { return iterator().slideBy(classifier).map(seq -> TreeSet.ofAll(tree.comparator(), seq)); } @Override public Iterator> sliding(int size) { return sliding(size, 1); } @Override public Iterator> sliding(int size, int 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(int 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(int 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(ignore -> new java.util.TreeSet<>(comparator())); } @SuppressWarnings("unchecked") @Override public TreeSet union(Set elements) { Objects.requireNonNull(elements, "elements is null"); if (elements instanceof TreeSet) { final TreeSet that = (TreeSet) elements; return that.isEmpty() ? this : new TreeSet<>(tree.union(that.tree)); } 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(Comparators.naturalComparator(), i1), i2 -> TreeSet.ofAll(Comparators.naturalComparator(), i2)); } @Override public Tuple3, TreeSet, TreeSet> unzip3( Function> unzipper) { Objects.requireNonNull(unzipper, "unzipper is null"); return iterator().unzip3(unzipper).map( i1 -> TreeSet.ofAll(Comparators.naturalComparator(), i1), i2 -> TreeSet.ofAll(Comparators.naturalComparator(), i2), i3 -> TreeSet.ofAll(Comparators.naturalComparator(), i3)); } @Override public TreeSet> zip(Iterable that) { return zipWith(that, Tuple::of); } @Override public TreeSet zipWith(Iterable that, BiFunction mapper) { Objects.requireNonNull(that, "that is null"); Objects.requireNonNull(mapper, "mapper is null"); return TreeSet.ofAll(Comparators.naturalComparator(), iterator().zipWith(that, mapper)); } @Override public TreeSet> zipAll(Iterable that, T thisElem, U thatElem) { Objects.requireNonNull(that, "that is null"); final Comparator> tuple2Comparator = Tuple2.comparator(tree.comparator(), Comparators.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()); } @Override public SortedSet zipWithIndex(BiFunction mapper) { return TreeSet.ofAll(Comparators.naturalComparator(), iterator().zipWithIndex(mapper)); } // -- Object @Override public boolean equals(Object o) { return Collections.equals(this, o); } @Override public int hashCode() { return Collections.hashUnordered(this); } @Override public String stringPrefix() { return "TreeSet"; } @Override public String toString() { return mkString(stringPrefix() + "(", ", ", ")"); } }