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

javaslang.collection.Seq Maven / Gradle / Ivy

Go to download

A Java implementation of a KillBill Payment Plugin that uses Authorize.Net as a payment gateway

There is a newer version: 2.8.196
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.Function1;
import javaslang.Tuple;
import javaslang.Tuple2;
import javaslang.Tuple3;
import javaslang.control.Option;

import java.util.Comparator;
import java.util.Objects;
import java.util.function.*;

/**
 * Interface for immutable sequential data structures.
 * 

* Creation: * *

    *
  • {@link #unit(Iterable)}
  • *
* * Filtering: * *
    *
  • {@link #remove(Object)}
  • *
  • {@link #removeAll(Object)}
  • *
  • {@link #removeAll(Iterable)}
  • *
  • {@link #removeAt(int)}
  • *
  • {@link #removeFirst(Predicate)}
  • *
  • {@link #removeLast(Predicate)}
  • *
* * Mutation: * *
    *
  • {@link #append(Object)}
  • *
  • {@link #appendAll(Iterable)}
  • *
  • {@link #insert(int, Object)}
  • *
  • {@link #insertAll(int, Iterable)}
  • *
  • {@link #prepend(Object)}
  • *
  • {@link #prependAll(Iterable)}
  • *
  • {@link #update(int, Object)}
  • *
* * Selection: * *
    *
  • {@link #get(int)}
  • *
  • {@link #indexOf(Object)}
  • *
  • {@link #indexOf(Object, int)}
  • *
  • {@link #lastIndexOf(Object)}
  • *
  • {@link #lastIndexOf(Object, int)}
  • *
  • {@link #slice(long, long)}
  • *
  • {@link #subSequence(int)}
  • *
  • {@link #subSequence(int, int)}
  • *
* * Transformation: * *
    *
  • {@link #crossProduct()}
  • *
  • {@link #crossProduct(int)}
  • *
  • {@link #crossProduct(Iterable)}
  • *
  • {@link #combinations()}
  • *
  • {@link #combinations(int)}
  • *
  • {@link #intersperse(Object)}
  • *
  • {@link #padTo(int, Object)}
  • *
  • {@link #permutations()}
  • *
  • {@link #reverse()}
  • *
  • {@link #sorted()}
  • *
  • {@link #sorted(Comparator)}
  • *
  • {@link #splitAt(long)}
  • *
  • {@link #unzip(Function)}
  • *
  • {@link #zip(Iterable)}
  • *
  • {@link #zipAll(Iterable, Object, Object)}
  • *
  • {@link #zipWithIndex()}
  • *
* * Traversal: * *
    *
  • {@link #iterator(int)}
  • *
* * @param Component type * @author Daniel Dietrich * @since 1.1.0 */ public interface Seq extends Traversable, Function1 { long serialVersionUID = 1L; /** * Narrows a widened {@code Seq} to {@code Seq} * by performing a type safe-cast. This is eligible because immutable/read-only * collections are covariant. * * @param seq A {@code Seq}. * @param Component type of the {@code Seq}. * @return the given {@code seq} instance as narrowed type {@code Seq}. */ @SuppressWarnings("unchecked") static Seq narrow(Seq seq) { return (Seq) seq; } /** * 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); } /** * Appends an element to this. * * @param element An element * @return A new Seq containing the given element appended to this elements */ Seq 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 appendAll(Iterable elements); /** * Returns the union of all combinations from k = 0 to length(). *

* Examples: *

     * 
     * [].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
     * ]
     * 
     * 
* * @return the combinations of this */ Seq> 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 Combination */ Seq> combinations(int k); /** * Tests whether this sequence contains a given sequence as a slice. *

* Note: may not terminate for infinite-sized collections. * * @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 that) { Objects.requireNonNull(that, "that is null"); return indexOfSlice(that) >= 0; } /** * Calculates the cross product (, i.e. square) of {@code this x this}. *

* Example: *

     * 
     * // = 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();
     * 
     * 
* * @return a new Iterator containing the square of {@code this} */ default Iterator> crossProduct() { return crossProduct(this); } /** * Calculates the n-ary cartesian power (or cross product or simply product) of this. *

* Example: *

     * 
     * // = ((A,A), (A,B), (A,C), ..., (B,A), (B,B), ..., (Z,Y), (Z,Z))
     * CharSeq.rangeClosed('A', 'Z').crossProduct(2);
     * 
     * 
* * @param power the number of cartesian multiplications * @return A new Iterator representing the n-ary cartesian power of this */ Iterator> crossProduct(int power); /** * Calculates the cross product {@code this x that}. *

* Example: *

     * 
     * // = 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');
     * 
     * 
* * @param that Another iterable * @param Component type * @return a new Iterator containing the cross product {@code this x that} * @throws NullPointerException if that is null */ default Iterator> crossProduct(Iterable that) { Objects.requireNonNull(that, "that is null"); final Stream other = Stream.ofAll(that); return Iterator.ofAll(this).flatMap(a -> other.map((Function>) b -> Tuple.of(a, b))); } /** * Tests whether this sequence ends with the given sequence. *

* 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 that) { Objects.requireNonNull(that, "that is null"); Iterator i = this.iterator().drop(length() - that.length()); Iterator 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 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); /** * Finds first index where this sequence contains a given sequence as a slice. *

* Note: may not terminate for infinite-sized collections. * * @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 that) { Objects.requireNonNull(that, "that is null"); return indexOfSlice(that, 0); } /** * 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-sized collections. * * @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. */ default int indexOfSlice(Iterable that, int from) { Objects.requireNonNull(that, "that is null"); class Util { int indexOfSlice(Seq t, Seq slice, int from) { if (t.isEmpty()) { return from == 0 && slice.isEmpty() ? 0 : -1; } if (from <= 0 && checkPrefix(t, slice)) { return 0; } int idx = indexOfSlice(t.tail(), slice, from - 1); return idx >= 0 ? idx + 1 : -1; } private boolean checkPrefix(Seq t, Seq prefix) { return prefix.isEmpty() || (!t.isEmpty() && Objects.equals(t.head(), prefix.head()) && checkPrefix(t.tail(), prefix.tail())); } } return new Util().indexOfSlice(this, unit(that), from); } /** * Finds index of first element satisfying some predicate. * * @param p 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 p) { return indexWhere(p, 0); } /** * 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 predicate, int 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 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 insertAll(int index, Iterable elements); /** * Inserts an element between all elements of this Traversable. * * @param element An element. * @return an interspersed version of this */ Seq 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 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); } /** * 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 predicate) { return lastIndexWhere(predicate, length() - 1); } /** * 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 predicate, int end); /** * 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); /** * Finds last index where this sequence contains a given sequence as a slice. *

* Note: will not terminate for infinite-sized collections. * * @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 that) { Objects.requireNonNull(that, "that is null"); return lastIndexOfSlice(that, Integer.MAX_VALUE); } /** * 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 that, int end); /** * A copy of this sequence with an element appended until a given target length is reached. * * @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 element so that the resulting sequence has a length of at least length. */ Seq padTo(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 patch(int from, Iterable that, int replaced); /** * Computes all unique permutations. *

* Example: *

     * 
     * [].permutations() = []
     *
     * [1,2,3].permutations() = [
     *   [1,2,3],
     *   [1,3,2],
     *   [2,1,3],
     *   [2,3,1],
     *   [3,1,2],
     *   [3,2,1]
     * ]
     * 
     * 
* * @return this unique permutations */ Seq> 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 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 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 prependAll(Iterable 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 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 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 removeAll(Iterable elements); /** * 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 removeAt(int index); /** * Removes the first occurrence that satisfy predicate * * @param predicate an predicate * @return a new Seq */ Seq removeFirst(Predicate predicate); /** * Removes the last occurrence that satisfy predicate * * @param predicate an predicate * @return a new Seq */ Seq removeLast(Predicate predicate); /** * Reverses the order of elements. * * @return the reversed elements. */ Seq reverse(); /** * An iterator yielding elements in reversed order. *

* 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 reverseIterator(); /** * Computes length of longest segment whose elements all satisfy some predicate. * * Note: may not terminate for infinite-sized collections. * * @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 predicate, int from); /** * Returns a Seq that is a slice of this. The slice begins with the element at the specified * {@code beginIndex} and extends to the element at index {@code endIndex - 1}. *

* Examples: * *

     * 
     * 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)
     * 
     * 
* * 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 slice(long beginIndex, long 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 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 sorted(Comparator comparator); /** * Sorts this elements by comparing the elements in a different domain, using the given {@code mapper}. * * @param mapper A mapper * @param The domain where elements are compared * @return a sorted version of this */ > Seq sortBy(Function 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 The domain where elements are compared * @return a sorted version of this */ Seq sortBy(Comparator comparator, Function 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 Tuple containing the first n and the remaining elements. */ Tuple2, ? extends Seq> splitAt(long 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> splitAt(Predicate 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> splitAtInclusive(Predicate 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 that) { return startsWith(that, 0); } /** * Tests whether this list contains the given sequence at a given index. *

* 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 that, int offset) { Objects.requireNonNull(that, "that is null"); if (offset < 0) return false; Iterator i = this.iterator().drop(offset); java.util.Iterator 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. *

* Examples: * *

     * 
     * 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
     * 
     * 
* * See also {@link #drop(long)} 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 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}. *

* Examples: * *

     * 
     * 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
     * 
     * 
* * See also {@link #slice(long, long)} 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, * if {@code endIndex} is greater than {@code length()}, * or if {@code beginIndex} is greater than {@code endIndex} */ Seq subSequence(int beginIndex, int endIndex); Seq unit(Iterable iterable); /** * Updates the given element at the specified index. * * @param index an index * @param element an element * @return a new Seq consisting of this elements and the given element is set at the given index * @throws IndexOutOfBoundsException if this is empty, index < 0 or index >= length() */ Seq update(int index, T element); /** * 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. *

* 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, (-(insertion point) - 1). The * insertion point 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} */ 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. *

* 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, (-(insertion point) - 1). The * insertion point 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 comparator); // -- Adjusted return types of Traversable methods @Override Seq distinct(); @Override Seq distinctBy(Comparator comparator); @Override Seq distinctBy(Function keyExtractor); @Override Seq drop(long n); @Override Seq dropRight(long n); @Override Seq dropUntil(Predicate predicate); @Override Seq dropWhile(Predicate predicate); @Override Seq filter(Predicate predicate); @Override Seq flatMap(Function> mapper); @Override default U foldRight(U zero, BiFunction f) { Objects.requireNonNull(f, "f is null"); return reverse().foldLeft(zero, (xs, x) -> f.apply(x, xs)); } @Override Map> groupBy(Function classifier); @Override Iterator> grouped(long size); @Override Seq init(); @Override Option> initOption(); @Override Seq map(Function mapper); @Override Tuple2, ? extends Seq> partition(Predicate predicate); @Override Seq peek(Consumer action); @Override Seq replace(T currentElement, T newElement); @Override Seq replaceAll(T currentElement, T newElement); @Override Seq retainAll(Iterable elements); @Override Seq scan(T zero, BiFunction operation); @Override Seq scanLeft(U zero, BiFunction operation); @Override Seq scanRight(U zero, BiFunction operation); @Override Iterator> sliding(long size); @Override Iterator> sliding(long size, long step); @Override Tuple2, ? extends Seq> span(Predicate predicate); @Override Seq tail(); @Override Option> tailOption(); @Override Seq take(long n); @Override Seq takeRight(long n); @Override Seq takeUntil(Predicate predicate); @Override Seq takeWhile(Predicate predicate); @Override Tuple2, ? extends Seq> unzip(Function> unzipper); @Override Tuple3, ? extends Seq, ? extends Seq> unzip3(Function> unzipper); @Override Seq> zip(Iterable that); @Override Seq> zipAll(Iterable that, T thisElem, U thatElem); @Override Seq> zipWithIndex(); }