/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/.ɪᴏ * ᶜᵒᵖʸʳᶦᵍʰᵗ ᵇʸ ᵛᵃᵛʳ ⁻ ˡᶦᶜᵉⁿˢᵉᵈ ᵘⁿᵈᵉʳ ᵗʰᵉ ᵃᵖᵃᶜʰᵉ ˡᶦᶜᵉⁿˢᵉ ᵛᵉʳˢᶦᵒⁿ ᵗʷᵒ ᵈᵒᵗ ᶻᵉʳᵒ */ package io.vavr.collection; import io.vavr.*; import io.vavr.control.Option; import java.io.Serializable; import java.util.Comparator; import java.util.Objects; import java.util.function.*; /** * Interface for immutable sequential data structures. * <p> * Basic operations: * * <ul> * <li>{@link #append(Object)}</li> * <li>{@link #appendAll(Iterable)}</li> * <li>{@link #insert(int, Object)}</li> * <li>{@link #insertAll(int, Iterable)}</li> * <li>{@link #prepend(Object)}</li> * <li>{@link #prependAll(Iterable)}</li> * <li>{@link #update(int, Object)}</li> * </ul> * * Filtering: * * <ul> * <li>{@link #remove(Object)}</li> * <li>{@link #removeAll(Object)}</li> * <li>{@link #removeAll(Iterable)}</li> * <li>{@link #removeAt(int)}</li> * <li>{@link #removeFirst(Predicate)}</li> * <li>{@link #removeLast(Predicate)}</li> * </ul> * * Selection: * * <ul> * <li>{@link #get(int)}</li> * <li>{@link #indexOf(Object)}</li> * <li>{@link #indexOf(Object, int)}</li> * <li>{@link #lastIndexOf(Object)}</li> * <li>{@link #lastIndexOf(Object, int)}</li> * <li>{@link #slice(int, int)}</li> * <li>{@link #subSequence(int)}</li> * <li>{@link #subSequence(int, int)}</li> * </ul> * * Transformation: * * <ul> * <li>{@link #crossProduct()}</li> * <li>{@link #crossProduct(int)}</li> * <li>{@link #crossProduct(Iterable)}</li> * <li>{@link #combinations()}</li> * <li>{@link #combinations(int)}</li> * <li>{@link #intersperse(Object)}</li> * <li>{@link #padTo(int, Object)}</li> * <li>{@link #permutations()}</li> * <li>{@link #reverse()}</li> * <li>{@link #shuffle()}</li> * <li>{@link #sorted()}</li> * <li>{@link #sorted(Comparator)}</li> * <li>{@link #splitAt(int)}</li> * <li>{@link #unzip(Function)}</li> * <li>{@link #zip(Iterable)}</li> * <li>{@link #zipAll(Iterable, Object, Object)}</li> * <li>{@link #zipWithIndex()}</li> * </ul> * * Traversal: * * <ul> * <li>{@link #iterator(int)}</li> * </ul> * * Views: * * <ul> * <li>{@link #asJava()}</li> * <li>{@link #asJava(Consumer)}</li> * <li>{@link #asJavaMutable()}</li> * <li>{@link #asJavaMutable(Consumer)}</li> * </ul> * * @param <T> Component type * @author Daniel Dietrich */ public interface Seq<T> extends Traversable<T>, Function1<Integer, T>, Serializable { long serialVersionUID = 1L; /** * Narrows a widened {@code Seq<? extends T>} to {@code Seq<T>} * by performing a type-safe cast. This is eligible because immutable/read-only * collections are covariant. * * @param seq A {@code Seq}. * @param <T> Component type of the {@code Seq}. * @return the given {@code seq} instance as narrowed type {@code Seq<T>}. */ @SuppressWarnings("unchecked") static <T> Seq<T> narrow(Seq<? extends T> seq) { return (Seq<T>) seq; } /** * Appends an element to this. * * @param element An element * @return A new Seq containing the given element appended to this elements */ Seq<T> append(T element); /** * Appends all given elements to this. * * @param elements An Iterable of elements * @return A new Seq containing the given elements appended to this elements * @throws NullPointerException if {@code elements} is null */ Seq<T> appendAll(Iterable<? extends T> elements); /** * A {@code Seq} is a partial function which returns the element at the specified index by calling * {@linkplain #get(int)}. * * @param index an index * @return the element at the given index * @throws IndexOutOfBoundsException if this is empty, index < 0 or index >= length() */ @Override default T apply(Integer index) { return get(index); } /** * Creates an <strong>immutable</strong> {@link java.util.List} view on top of this {@code Seq}, * i.e. calling mutators will result in {@link UnsupportedOperationException} at runtime. * <p> * The difference to conversion methods {@code toJava*()} is that * * <ul> * <li>A view is created in O(1) (constant time) whereas conversion takes O(n) (linear time), with n = collection size.</li> * <li>The operations on a view have the same performance characteristics than the underlying persistent Vavr collection whereas the performance characteristics of a converted collection are those of the Java standard collections.</li> * </ul> * * Please note that our immutable {@code java.util.List} view throws {@code UnsupportedOperationException} before * checking method arguments. Java does handle this case inconsistently. * * @return A new immutable {@link java.util.Collection} view on this {@code Traversable}. */ @GwtIncompatible java.util.List<T> asJava(); /** * Creates an <strong>immutable</strong> {@link java.util.List} view on top of this {@code Seq} * that is passed to the given {@code action}. * * @param action A side-effecting unit of work that operates on an immutable {@code java.util.List} view. * @return this instance * @see Seq#asJava() */ @GwtIncompatible Seq<T> asJava(Consumer<? super java.util.List<T>> action); /** * Creates a <strong>mutable</strong> {@link java.util.List} view on top of this {@code Seq}, * i.e. all mutator methods of the {@link java.util.List} are implemented. * * @return A new mutable {@link java.util.Collection} view on this {@code Traversable}. * @see Seq#asJava() */ @GwtIncompatible java.util.List<T> asJavaMutable(); /** * Creates a <strong>mutable</strong> {@link java.util.List} view on top of this {@code Seq} * that is passed to the given {@code action}. * * @param action A side-effecting unit of work that operates on a mutable {@code java.util.List} view. * @return this instance, if only read operations are performed on the {@code java.util.List} view or a new instance of this type, if write operations are performed on the {@code java.util.List} view. * @see Seq#asJavaMutable() */ @GwtIncompatible Seq<T> asJavaMutable(Consumer<? super java.util.List<T>> action); @Override <R> Seq<R> collect(PartialFunction<? super T, ? extends R> partialFunction); /** * Returns the union of all combinations from k = 0 to length(). * <p> * Examples: * <pre> * <code> * [].combinations() = [[]] * * [1,2,3].combinations() = [ * [], // k = 0 * [1], [2], [3], // k = 1 * [1,2], [1,3], [2,3], // k = 2 * [1,2,3] // k = 3 * ] * </code> * </pre> * * @return the combinations of this */ Seq<? extends Seq<T>> combinations(); /** * Returns the k-combination of this traversable, i.e. all subset of this of k distinct elements. * * @param k Size of subsets * @return the k-combination of this elements * @see <a href="http://en.wikipedia.org/wiki/Combination">Combination</a> */ Seq<? extends Seq<T>> combinations(int k); /** * Tests whether this sequence contains a given sequence as a slice. * <p> * Note: may not terminate for infinite sequences. * * @param that the sequence to test * @return true if this sequence contains a slice with the same elements as that, otherwise false. * @throws NullPointerException if {@code that} is null. */ default boolean containsSlice(Iterable<? extends T> that) { Objects.requireNonNull(that, "that is null"); return indexOfSlice(that) >= 0; } /** * Calculates the cross product (, i.e. square) of {@code this x this}. * <p> * Example: * <pre> * <code> * // = List of Tuples (1, 1), (1, 2), (1, 3), (2, 1), (2, 2), (2, 3), (3, 1), (3, 2), (3, 3) * List.of(1, 2, 3).crossProduct(); * </code> * </pre> * * @return a new Iterator containing the square of {@code this} */ default Iterator<Tuple2<T, T>> crossProduct() { return crossProduct(this); } /** * Calculates the n-ary cartesian power (or <em>cross product</em> or simply <em>product</em>) of this. * <p> * Example: * <pre> * <code> * // = ((A,A), (A,B), (A,C), ..., (B,A), (B,B), ..., (Z,Y), (Z,Z)) * CharSeq.rangeClosed('A', 'Z').crossProduct(2); * </code> * </pre> * <p> * Cartesian power of negative value will return empty iterator. * <p> * Example: * <pre> * <code> * // = () * CharSeq.rangeClosed('A', 'Z').crossProduct(-1); * </code> * </pre> * * @param power the number of cartesian multiplications * @return A new Iterator representing the n-ary cartesian power of this */ Iterator<? extends Seq<T>> crossProduct(int power); /** * Calculates the cross product {@code this x that}. * <p> * Example: * <pre> * <code> * // = List of Tuples (1, 'a'), (1, 'b'), (2, 'a'), (2, 'b'), (3, 'a'), (3, 'b') * List.of(1, 2, 3).crossProduct(List.of('a', 'b'); * </code> * </pre> * * @param that Another iterable * @param <U> Component type * @return a new Iterator containing the cross product {@code this x that} * @throws NullPointerException if that is null */ default <U> Iterator<Tuple2<T, U>> crossProduct(Iterable<? extends U> that) { Objects.requireNonNull(that, "that is null"); final Stream<U> other = Stream.ofAll(that); return Iterator.ofAll(this).flatMap(a -> other.map(b -> Tuple.of(a, b))); } /** * Tests whether this sequence ends with the given sequence. * <p> * Note: If the both the receiver object this and the argument that are infinite sequences this method may not terminate. * * @param that the sequence to test * @return true if this sequence has that as a suffix, false otherwise. */ default boolean endsWith(Seq<? extends T> that) { Objects.requireNonNull(that, "that is null"); final Iterator<T> i = this.iterator().drop(length() - that.length()); final Iterator<? extends T> j = that.iterator(); while (i.hasNext() && j.hasNext()) { if (!Objects.equals(i.next(), j.next())) { return false; } } return !j.hasNext(); } /** * Returns the element at the specified index. * * @param index an index * @return the element at the given index * @throws IndexOutOfBoundsException if this is empty, index < 0 or index >= length() */ T get(int index); /** * Returns the index of the first occurrence of the given element or -1 if this does not contain the given element. * * @param element an element * @return the index of the first occurrence of the given element */ default int indexOf(T element) { return indexOf(element, 0); } /** * Returns the index of the first occurrence of the given element as an {@code Option} * * @param element an element * @return {@code Some(index)} or {@code None} if not found. */ default Option<Integer> indexOfOption(T element) { return Collections.indexOption(indexOf(element)); } /** * Returns the index of the first occurrence of the given element after or at some start index * or -1 if this does not contain the given element. * * @param element an element * @param from start index * @return the index of the first occurrence of the given element */ int indexOf(T element, int from); /** * Returns the index of the first occurrence of the given element, * after or at some start index as an {@code Option} * * @param element an element * @param from start index * @return {@code Some(index)} or {@code None} if not found. */ default Option<Integer> indexOfOption(T element, int from) { return Collections.indexOption(indexOf(element, from)); } /** * Finds first index where this sequence contains a given sequence as a slice. * <p> * Note: may not terminate for infinite sequences. * * @param that the sequence to test * @return the first index such that the elements of this sequence starting at this index match * the elements of sequence that, or -1 of no such slice exists. * @throws NullPointerException if {@code that} is null. */ default int indexOfSlice(Iterable<? extends T> that) { return indexOfSlice(that, 0); } /** * Finds first index where this sequence contains a given sequence as an {@code Option} of a slice. * <p> * Note: may not terminate for infinite sequences. * * @param that the sequence to test * @return {@code Some(index)} or {@code None} if not found. */ default Option<Integer> indexOfSliceOption(Iterable<? extends T> that) { return Collections.indexOption(indexOfSlice(that)); } /** * Finds first index after or at a start index where this sequence contains a given sequence as a slice. * Note: may not terminate for infinite sequences. * * @param that the sequence to test * @param from the start index * @return the first index >= from such that the elements of this sequence starting at this index match * the elements of sequence that, or -1 of no such slice exists. * @throws NullPointerException if {@code that} is null. */ int indexOfSlice(Iterable<? extends T> that, int from); /** * Finds first index after or at a start index where this sequence contains a given sequence as an {@code Option} of a slice. * Note: may not terminate for infinite sequences. * * @param that the sequence to test * @param from the start index * @return {@code Some(index)} or {@code None} if not found. */ default Option<Integer> indexOfSliceOption(Iterable<? extends T> that, int from) { return Collections.indexOption(indexOfSlice(that, from)); } /** * Finds index of first element satisfying some predicate. * * @param predicate the predicate used to test elements. * @return the index of the first element of this Seq that satisfies the given * {@code predicate}, or {@code -1}, if none exists. */ default int indexWhere(Predicate<? super T> predicate) { return indexWhere(predicate, 0); } /** * Finds index of first element satisfying some predicate as an {@code Option}. * * @param predicate the predicate used to test elements. * @return {@code Some(index)} or {@code None} if not found. */ default Option<Integer> indexWhereOption(Predicate<? super T> predicate) { return Collections.indexOption(indexWhere(predicate)); } /** * Finds index of the first element satisfying some predicate after or at * some start index. * * @param predicate the predicate used to test elements. * @param from the start index * @return the index {@code >= from} of the first element of this Seq that * satisfies the given {@code predicate}, or {@code -1}, if none exists. */ int indexWhere(Predicate<? super T> predicate, int from); /** * Finds index of the first element satisfying some predicate after or at * some start index as an {@code Option}. * * @param predicate the predicate used to test elements. * @param from the start index * @return {@code Some(index)} or {@code None} if not found. */ default Option<Integer> indexWhereOption(Predicate<? super T> predicate, int from) { return Collections.indexOption(indexWhere(predicate, from)); } /** * Inserts the given element at the specified index. * * @param index an index * @param element an element * @return a new Seq, where the given element is inserted into this at the given index * @throws IndexOutOfBoundsException if this is empty, index < 0 or index >= length() */ Seq<T> insert(int index, T element); /** * Inserts the given elements at the specified index. * * @param index an index * @param elements An Iterable of elements * @return a new Seq, where the given elements are inserted into this at the given index * @throws IndexOutOfBoundsException if this is empty, index < 0 or index >= length() */ Seq<T> insertAll(int index, Iterable<? extends T> elements); /** * Inserts an element between all elements of this Traversable. * * @param element An element. * @return an interspersed version of this */ Seq<T> intersperse(T element); /** * Returns an iterator of this elements starting at the given index. * The result is equivalent to {@code this.subSequence(index).iterator()}. * * @param index an index * @return a new Iterator, starting with the element at the given index or the empty Iterator, if index = length() * @throws IndexOutOfBoundsException if index < 0 or index > length() */ default Iterator<T> iterator(int index) { return subSequence(index).iterator(); } /** * Returns the index of the last occurrence of the given element or -1 if this does not contain the given element. * * @param element an element * @return the index of the last occurrence of the given element */ default int lastIndexOf(T element) { return lastIndexOf(element, Integer.MAX_VALUE); } /** * Returns the index of the last occurrence of the given element as an {@code Option}. * * @param element an element * @return {@code Some(index)} or {@code None} if not found. */ default Option<Integer> lastIndexOfOption(T element) { return Collections.indexOption(lastIndexOf(element)); } /** * Finds index of last element satisfying some predicate. * * @param predicate the predicate used to test elements. * @return the index of the last element of this Seq that satisfies the given {@code predicate}, or {@code -1}, * if none exists. */ default int lastIndexWhere(Predicate<? super T> predicate) { return lastIndexWhere(predicate, length() - 1); } /** * Finds index of last element satisfying some predicate as an {@code Option}. * * @param predicate the predicate used to test elements. * @return {@code Some(index)} or {@code None} if not found. */ default Option<Integer> lastIndexWhereOption(Predicate<? super T> predicate) { return Collections.indexOption(lastIndexWhere(predicate)); } /** * Finds index of last element satisfying some predicate before or at given * end index. * * @param predicate the predicate used to test elements. * @param end the maximum index of the search * @return the index {@code <= end} of the last element of this Seq that * satisfies the given {@code predicate}, or {@code -1}, if none exists. */ int lastIndexWhere(Predicate<? super T> predicate, int end); /** * Finds index of last element satisfying some predicate before or at given end index as an {@code Option}. * * @param predicate the predicate used to test elements. * @param end the maximum index of the search * @return {@code Some(index)} or {@code None} if not found. */ default Option<Integer> lastIndexWhereOption(Predicate<? super T> predicate, int end) { return Collections.indexOption(lastIndexWhere(predicate, end)); } /** * Turns this sequence into a plain function returning an Option result. * * @return a function that takes an index i and returns the value of * this sequence in a Some if the index is within bounds, otherwise a None. */ default Function1<Integer, Option<T>> lift() { return i -> (i >= 0 && i < length()) ? Option.some(apply(i)) : Option.none(); } /** * Returns the index of the last occurrence of the given element before or at a given end index * or -1 if this does not contain the given element. * * @param element an element * @param end the end index * @return the index of the last occurrence of the given element */ int lastIndexOf(T element, int end); /** * Returns the index of the last occurrence of the given element before or at a given end index as an {@code Option}. * * @param element an element * @param end the end index * @return {@code Some(index)} or {@code None} if not found. */ default Option<Integer> lastIndexOfOption(T element, int end) { return Collections.indexOption(lastIndexOf(element, end)); } /** * Finds last index where this sequence contains a given sequence as a slice. * <p> * Note: will not terminate for infinite sequences. * * @param that the sequence to test * @return the last index such that the elements of this sequence starting a this index match the elements * of sequence that, or -1 of no such slice exists. * @throws NullPointerException if {@code that} is null. */ default int lastIndexOfSlice(Iterable<? extends T> that) { return lastIndexOfSlice(that, Integer.MAX_VALUE); } /** * Finds last index where this sequence contains a given sequence as a slice as an {@code Option}. * * @param that the sequence to test * @return {@code Some(index)} or {@code None} if not found. */ default Option<Integer> lastIndexOfSliceOption(Iterable<? extends T> that) { return Collections.indexOption(lastIndexOfSlice(that)); } /** * Finds last index before or at a given end index where this sequence contains a given sequence as a slice. * * @param that the sequence to test * @param end the end index * @return the last index <= end such that the elements of this sequence starting at this index match * the elements of sequence that, or -1 of no such slice exists. * @throws NullPointerException if {@code that} is null. */ int lastIndexOfSlice(Iterable<? extends T> that, int end); /** * Finds last index before or at a given end index where this sequence contains a given sequence as a slice as an {@code Option}. * * @param that the sequence to test * @param end the end index * @return {@code Some(index)} or {@code None} if not found. */ default Option<Integer> lastIndexOfSliceOption(Iterable<? extends T> that, int end) { return Collections.indexOption(lastIndexOfSlice(that, end)); } /** * A copy of this sequence with an element appended until a given target length is reached. * <p> * Note: lazily-evaluated Seq implementations need to process all elements in order to gather the overall length. * * @param length the target length * @param element the padding element * @return a new sequence consisting of all elements of this sequence followed by the minimal number * of occurrences of <code>element</code> so that the resulting sequence has a length of at least <code>length</code>. */ Seq<T> padTo(int length, T element); /** * A copy of this sequence with an element prepended until a given target length is reached. * <p> * Note: lazily-evaluated Seq implementations need to process all elements in order to gather the overall length. * * @param length the target length * @param element the padding element * @return a new sequence consisting of all elements of this sequence prepended by the minimal number * of occurrences of <code>element</code> so that the resulting sequence has a length of at least <code>length</code>. */ Seq<T> leftPadTo(int length, T element); /** * Produces a new list where a slice of elements in this list is replaced by another sequence. * * @param from the index of the first replaced element * @param that sequence for replacement * @param replaced the number of elements to drop in the original list * @return a new sequence. */ Seq<T> patch(int from, Iterable<? extends T> that, int replaced); /** * Computes all unique permutations. * <p> * Example: * <pre> * <code> * [].permutations() = [] * * [1,2,3].permutations() = [ * [1,2,3], * [1,3,2], * [2,1,3], * [2,3,1], * [3,1,2], * [3,2,1] * ] * </code> * </pre> * * @return this unique permutations */ Seq<? extends Seq<T>> permutations(); /** * Returns the length of the longest prefix whose elements all satisfy some predicate. * * Note: may not terminate for infinite-sized collections. * * @param predicate the predicate used to test elements. * @return the length of the longest prefix of this general sequence such that every * element of the segment satisfies the predicate p. */ default int prefixLength(Predicate<? super T> predicate) { return segmentLength(predicate, 0); } /** * Prepends an element to this. * * @param element An element * @return A new Seq containing the given element prepended to this elements */ Seq<T> prepend(T element); /** * Prepends all given elements to this. * * @param elements An Iterable of elements * @return A new Seq containing the given elements prepended to this elements */ Seq<T> prependAll(Iterable<? extends T> elements); /** * Removes the first occurrence of the given element. * * @param element An element to be removed from this Seq. * @return a Seq containing all elements of this without the first occurrence of the given element. */ Seq<T> remove(T element); /** * Removes all occurrences of the given element. * * @param element An element to be removed from this Seq. * @return a Seq containing all elements of this but not the given element. */ Seq<T> removeAll(T element); /** * Removes all occurrences of the given elements. * * @param elements Elements to be removed from this Seq. * @return a Seq containing all elements of this but none of the given elements. * @throws NullPointerException if {@code elements} is null */ Seq<T> removeAll(Iterable<? extends T> elements); /** * Returns a new Seq consisting of all elements which do not satisfy the given predicate. * * @param predicate the predicate used to test elements * @return a new Seq * @throws NullPointerException if {@code predicate} is null */ Seq<T> removeAll(Predicate<? super T> predicate); /** * Removes the element at the specified position in this sequence. Shifts any subsequent elements to the left * (subtracts one from their indices). * * @param index position of element to remove * @return a sequence containing all elements of this without the element at the specified position. * @throws IndexOutOfBoundsException if this is empty, index < 0 or index >= length() */ Seq<T> removeAt(int index); /** * Removes the first occurrence that satisfy predicate * * @param predicate an predicate * @return a new Seq */ Seq<T> removeFirst(Predicate<T> predicate); /** * Removes the last occurrence that satisfy predicate * * @param predicate an predicate * @return a new Seq */ Seq<T> removeLast(Predicate<T> predicate); /** * Reverses the order of elements. * * @return the reversed elements. */ Seq<T> reverse(); /** * An iterator yielding elements in reversed order. * <p> * Note: {@code xs.reverseIterator()} is the same as {@code xs.reverse().iterator()} but might * be more efficient. * * @return an iterator yielding the elements of this Seq in reversed order */ Iterator<T> reverseIterator(); /** * Computes length of longest segment whose elements all satisfy some predicate. * <p> * Note: may not terminate for infinite sequences. * * @param predicate the predicate used to test elements. * @param from the index where the search starts. * @return the length of the longest segment of this sequence starting from index * from such that every element of the segment satisfies the predicate p. */ int segmentLength(Predicate<? super T> predicate, int from); /** * Randomize the order of the elements in the current sequence. * * @return a sequence with the same elements as the current sequence in a random order. */ Seq<T> shuffle(); /** * Returns a Seq that is a <em>slice</em> of this. The slice begins with the element at the specified * {@code beginIndex} and extends to the element at index {@code endIndex - 1}. * <p> * Examples: * * <pre> * <code> * List.of(1, 2, 3, 4).slice(1, 3); // = (2, 3) * List.of(1, 2, 3, 4).slice(0, 4); // = (1, 2, 3, 4) * List.of(1, 2, 3, 4).slice(2, 2); // = () * List.of(1, 2).slice(1, 0); // = () * List.of(1, 2).slice(-10, 10); // = (1, 2) * </code> * </pre> * * See also {@link #subSequence(int, int)} which throws in some cases instead of returning a sequence. * * @param beginIndex the beginning index, inclusive * @param endIndex the end index, exclusive * @return the specified slice */ Seq<T> slice(int beginIndex, int endIndex); /** * Sorts this elements according to their natural order. If this elements are not * {@code Comparable}, a {@code java.lang.ClassCastException} may be thrown. * * @return A sorted version of this * @throws ClassCastException if this elements are not {@code Comparable} */ Seq<T> sorted(); /** * Sorts this elements according to the provided {@code Comparator}. If this elements are not * {@code Comparable}, a {@code java.lang.ClassCastException} may be thrown. * * @param comparator A comparator * @return a sorted version of this */ Seq<T> sorted(Comparator<? super T> comparator); /** * Sorts this elements by comparing the elements in a different domain, using the given {@code mapper}. * * @param mapper A mapper * @param <U> The domain where elements are compared * @return a sorted version of this */ <U extends Comparable<? super U>> Seq<T> sortBy(Function<? super T, ? extends U> mapper); /** * Sorts this elements by comparing the elements in a different domain, using the given {@code mapper}. * * @param comparator A comparator * @param mapper A mapper * @param <U> The domain where elements are compared * @return a sorted version of this */ <U> Seq<T> sortBy(Comparator<? super U> comparator, Function<? super T, ? extends U> mapper); /** * Splits a Seq at the specified index. The result of {@code splitAt(n)} is equivalent to * {@code Tuple.of(take(n), drop(n))}. * * @param n An index. * @return A {@link Tuple} containing the first n and the remaining elements. */ Tuple2<? extends Seq<T>, ? extends Seq<T>> splitAt(int n); /** * Splits a sequence at the first element which satisfies the {@link Predicate}, e.g. Tuple(init, element+tail). * * @param predicate An predicate * @return A {@link Tuple} containing divided sequences */ Tuple2<? extends Seq<T>, ? extends Seq<T>> splitAt(Predicate<? super T> predicate); /** * Splits a sequence at the first element which satisfies the {@link Predicate}, e.g. Tuple(init+element, tail). * * @param predicate An predicate * @return A {@link Tuple} containing divided sequences */ Tuple2<? extends Seq<T>, ? extends Seq<T>> splitAtInclusive(Predicate<? super T> predicate); /** * Tests whether this list starts with the given sequence. * * @param that the sequence to test * @return true if that is empty or that is prefix of this collection, false otherwise. */ default boolean startsWith(Iterable<? extends T> that) { return startsWith(that, 0); } /** * Tests whether this list contains the given sequence at a given index. * <p> * Note: If the both the receiver object this and the argument that are infinite sequences this method may not terminate. * * @param that the sequence to test * @param offset the index where the sequence is searched. * @return true if that is empty or that is prefix of this collection starting from the given offset, false otherwise. */ default boolean startsWith(Iterable<? extends T> that, int offset) { Objects.requireNonNull(that, "that is null"); if (offset < 0) { return false; } final Iterator<T> i = this.iterator().drop(offset); final java.util.Iterator<? extends T> j = that.iterator(); while (i.hasNext() && j.hasNext()) { if (!Objects.equals(i.next(), j.next())) { return false; } } return !j.hasNext(); } /** * Returns a Seq that is a subsequence of this. The subsequence begins with the element at the specified * {@code beginIndex} and extends to the end of this Seq. * <p> * Examples: * * <pre> * <code> * List.of(1, 2).subSequence(0); // = (1, 2) * List.of(1, 2).subSequence(1); // = (2) * List.of(1, 2).subSequence(2); // = () * List.of(1, 2).subSequence(10); // throws IndexOutOfBoundsException * List.of(1, 2).subSequence(-10); // throws IndexOutOfBoundsException * </code> * </pre> * * See also {@link #drop(int)} which is similar but does not throw. * * @param beginIndex the beginning index, inclusive * @return the specified subsequence * @throws IndexOutOfBoundsException if {@code beginIndex} is negative or larger than the length of this * {@code String} object. */ Seq<T> subSequence(int beginIndex); /** * Returns a Seq that is a subsequence of this. The subsequence begins with the element at the specified * {@code beginIndex} and extends to the element at index {@code endIndex - 1}. * <p> * Examples: * * <pre> * <code> * List.of(1, 2, 3, 4).subSequence(1, 3); // = (2, 3) * List.of(1, 2, 3, 4).subSequence(0, 4); // = (1, 2, 3, 4) * List.of(1, 2, 3, 4).subSequence(2, 2); // = () * List.of(1, 2).subSequence(1, 0); // throws IndexOutOfBoundsException * List.of(1, 2).subSequence(-10, 1); // throws IndexOutOfBoundsException * List.of(1, 2).subSequence(0, 10); // throws IndexOutOfBoundsException * </code> * </pre> * * See also {@link #slice(int, int)} which returns an empty sequence instead of throwing. * * @param beginIndex the beginning index, inclusive * @param endIndex the end index, exclusive * @return the specified subsequence * @throws IndexOutOfBoundsException if {@code beginIndex} or {@code endIndex} is negative or * if {@code endIndex} is greater than {@code length()} * @throws IllegalArgumentException if {@code beginIndex} is greater than {@code endIndex} */ Seq<T> subSequence(int beginIndex, int endIndex); /** * Updates the given element at the specified index. * * @param index an index * @param element an element * @return a new Seq consisting of all previous elements, with a single one (at the given index), changed to the new value. * @throws IndexOutOfBoundsException if this is empty, index < 0 or index >= length() */ Seq<T> update(int index, T element); /** * Updates the given element at the specified index using the specified function. * * @param index an index * @param updater a function transforming the previous value * @return a new Seq consisting of all previous elements, with a single one (at the given index), changed to the new value. * @throws IndexOutOfBoundsException if this is empty, index < 0 or index >= length() */ Seq<T> update(int index, Function<? super T, ? extends T> updater); /** * Searches this sequence for a specific element. The sequence must already be sorted into ascending natural * order. If it is not sorted, the results are undefined. * <p> * If this sequence is an `IndexedSeq`, a binary search is used. Otherwise, a linear search is used. * * @param element the element to find * @return the index of the search element, if it is contained in the sequence; * otherwise, <tt>(-(<i>insertion point</i>) - 1)</tt>. The * <i>insertion point</i> is defined as the point at which the * element would be inserted into the sequence. Note that this guarantees that * the return value will be >= 0 if and only if the element is found. * @throws ClassCastException if T cannot be cast to {@code Comparable<? super T>} */ int search(T element); /** * Searches this sequence for a specific element. The sequence must already be sorted into ascending order * according to the specified comparator. If it is not sorted, the results are undefined. * <p> * If this sequence is an `IndexedSeq`, a binary search is used. Otherwise, a linear search is used. * * @param element the element to find * @param comparator the comparator by which this sequence is ordered * @return the index of the search element, if it is contained in the sequence; * otherwise, <tt>(-(<i>insertion point</i>) - 1)</tt>. The * <i>insertion point</i> is defined as the point at which the * element would be inserted into the sequence. Note that this guarantees that * the return value will be >= 0 if and only if the element is found. */ int search(T element, Comparator<? super T> comparator); // -- Adjusted return types of Traversable methods @Override Seq<T> distinct(); @Override Seq<T> distinctBy(Comparator<? super T> comparator); @Override <U> Seq<T> distinctBy(Function<? super T, ? extends U> keyExtractor); @Override Seq<T> drop(int n); @Override Seq<T> dropUntil(Predicate<? super T> predicate); @Override Seq<T> dropWhile(Predicate<? super T> predicate); @Override Seq<T> dropRight(int n); /** * Drops elements until the predicate holds for the current element, starting from the end. * * @param predicate A condition tested subsequently for this elements, starting from the end. * @return a new instance consisting of all elements starting from the last one which does satisfy the given * predicate. * @throws NullPointerException if {@code predicate} is null */ Seq<T> dropRightUntil(Predicate<? super T> predicate); /** * Drops elements while the predicate holds for the current element, starting from the end. * <p> * Note: This is essentially the same as {@code dropRightUntil(predicate.negate())}. * It is intended to be used with method references, which cannot be negated directly. * * @param predicate A condition tested subsequently for this elements, starting from the end. * @return a new instance consisting of all elements starting from the last one which does not satisfy the * given predicate. * @throws NullPointerException if {@code predicate} is null */ Seq<T> dropRightWhile(Predicate<? super T> predicate); @Override Seq<T> filter(Predicate<? super T> predicate); @Override <U> Seq<U> flatMap(Function<? super T, ? extends Iterable<? extends U>> mapper); @Override default <U> U foldRight(U zero, BiFunction<? super T, ? super U, ? extends U> f) { Objects.requireNonNull(f, "f is null"); return reverse().foldLeft(zero, (xs, x) -> f.apply(x, xs)); } @Override <C> Map<C, ? extends Seq<T>> groupBy(Function<? super T, ? extends C> classifier); @Override Iterator<? extends Seq<T>> grouped(int size); @Override Seq<T> init(); @Override Option<? extends Seq<T>> initOption(); @Override <U> Seq<U> map(Function<? super T, ? extends U> mapper); @Override Seq<T> orElse(Iterable<? extends T> other); @Override Seq<T> orElse(Supplier<? extends Iterable<? extends T>> supplier); @Override Tuple2<? extends Seq<T>, ? extends Seq<T>> partition(Predicate<? super T> predicate); @Override Seq<T> peek(Consumer<? super T> action); @Override Seq<T> replace(T currentElement, T newElement); @Override Seq<T> replaceAll(T currentElement, T newElement); @Override Seq<T> retainAll(Iterable<? extends T> elements); @Override Seq<T> scan(T zero, BiFunction<? super T, ? super T, ? extends T> operation); @Override <U> Seq<U> scanLeft(U zero, BiFunction<? super U, ? super T, ? extends U> operation); @Override <U> Seq<U> scanRight(U zero, BiFunction<? super T, ? super U, ? extends U> operation); @Override Iterator<? extends Seq<T>> slideBy(Function<? super T, ?> classifier); @Override Iterator<? extends Seq<T>> sliding(int size); @Override Iterator<? extends Seq<T>> sliding(int size, int step); @Override Tuple2<? extends Seq<T>, ? extends Seq<T>> span(Predicate<? super T> predicate); @Override Seq<T> tail(); @Override Option<? extends Seq<T>> tailOption(); @Override Seq<T> take(int n); @Override Seq<T> takeRight(int n); @Override Seq<T> takeUntil(Predicate<? super T> predicate); @Override Seq<T> takeWhile(Predicate<? super T> predicate); @Override <T1, T2> Tuple2<? extends Seq<T1>, ? extends Seq<T2>> unzip(Function<? super T, Tuple2<? extends T1, ? extends T2>> unzipper); @Override <T1, T2, T3> Tuple3<? extends Seq<T1>, ? extends Seq<T2>, ? extends Seq<T3>> unzip3(Function<? super T, Tuple3<? extends T1, ? extends T2, ? extends T3>> unzipper); @Override <U> Seq<Tuple2<T, U>> zip(Iterable<? extends U> that); @Override <U, R> Seq<R> zipWith(Iterable<? extends U> that, BiFunction<? super T, ? super U, ? extends R> mapper); @Override <U> Seq<Tuple2<T, U>> zipAll(Iterable<? extends U> that, T thisElem, U thatElem); @Override Seq<Tuple2<T, Integer>> zipWithIndex(); @Override <U> Seq<U> zipWithIndex(BiFunction<? super T, ? super Integer, ? extends U> mapper); /** * Turns this sequence from a partial function into a total function that * returns defaultValue for all indexes that are out of bounds. * * @param defaultValue default value to return for out of bound indexes * @return a total function from index to T */ default Function1<Integer, T> withDefaultValue(T defaultValue) { return i -> (i >= 0 && i < length()) ? apply(i) : defaultValue; } /** * Turns this sequence from a partial function into a total function that * returns a value computed by defaultFunction for all indexes that are out of bounds. * * @param defaultFunction function to evaluate for all out of bounds indexes. * @return a total function from index to T */ default Function1<Integer, T> withDefault(Function<? super Integer, ? extends T> defaultFunction) { return i -> (i >= 0 && i < length()) ? apply(i) : defaultFunction.apply(i); } @Override default boolean isSequential() { return true; } }