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

net.sf.staccatocommons.collections.stream.Stream Maven / Gradle / Ivy

/**
 *  Copyright (c) 2010-2012, The StaccatoCommons Team
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU Lesser General Public License as published by
 *  the Free Software Foundation; version 3 of the License.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Lesser General Public License for more details.
 */

package net.sf.staccatocommons.collections.stream;

import java.io.IOException;
import java.io.Serializable;
import java.io.Writer;
import java.util.Collection;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;

import net.sf.staccatocommons.collections.EmptySourceException;
import net.sf.staccatocommons.collections.iterable.Iterables;
import net.sf.staccatocommons.collections.restrictions.Projection;
import net.sf.staccatocommons.collections.restrictions.Repeatable;
import net.sf.staccatocommons.defs.Applicable;
import net.sf.staccatocommons.defs.Applicable2;
import net.sf.staccatocommons.defs.Evaluable;
import net.sf.staccatocommons.defs.Evaluable2;
import net.sf.staccatocommons.defs.Executable;
import net.sf.staccatocommons.defs.ProtoMonad;
import net.sf.staccatocommons.defs.Thunk;
import net.sf.staccatocommons.defs.function.Function;
import net.sf.staccatocommons.defs.function.Function2;
import net.sf.staccatocommons.defs.partial.ContainsAware;
import net.sf.staccatocommons.defs.partial.SizeAware;
import net.sf.staccatocommons.defs.reduction.Reduction;
import net.sf.staccatocommons.defs.tuple.Tuple2;
import net.sf.staccatocommons.defs.type.NumberType;
import net.sf.staccatocommons.iterators.thriter.Thriterator;
import net.sf.staccatocommons.lang.None;
import net.sf.staccatocommons.lang.Option;
import net.sf.staccatocommons.lang.tuple.Tuples;
import net.sf.staccatocommons.restrictions.check.NonNull;
import net.sf.staccatocommons.restrictions.check.NotNegative;

/**
 * A {@link Stream} is a lazy, rich-interfaced, {@link Iterable}, chained
 * functional-style object that can retrieve and process an arbitrary - and
 * potentially unbound - amount of other objects of a parameterized type. Such
 * objects are called elements, and are generated by another object, called
 * source. Some examples of elements and its source are:
 * 
    *
  • Elements in a collection
  • *
  • Files in a directory
  • *
  • Characters in a string
  • *
  • Lines in a file
  • *
  • Rows in a result set
  • *
  • Virtually anything that has sense to iterate through
  • *
* * Streams have the following properties: *
    *
  1. Operation oriented: A stream represents a single and eventually complex * transformation over a source of objects; it is not a * container
  2. *
  3. Reference Semantics: A stream internal state is meaningless, and Streams * do not override Object's {@link #equals(Object)}, {@link #hashCode()} nor * {@link #toString()}
  4. *
  5. Non persistent: Streams are not {@link Serializable} Thus, they should * not be used as attributes of long-living objects.
  6. *
  7. One-Message: Given a stream instance, only one message can be sent to it, * sending more than one message to it has an undefined result, as a * consequence, it may be iterated only once. There are three exceptions to this * rule, though: *
      *
    1. Methods inherited from {@link Object} like {@link #toString()} and * {@link #hashCode()}. None of those methods affect the transformation nor the * underlying source
    2. *
    3. {@link #isEmpty()}: it may be sent multiple times and grants consistent * results as long as no other message except of those at previous item is sent. * This message does not affect the transformation, but may modify the * underlying source
    4. *
    5. Streams returned by class or instance methods annotated with * {@link Repeatable}, like {@link #force()} or {@link Streams#cons(Object)}. * Such streams may be reused and receive any message any number of times, and * grant consistent results, including repeatable iteration order.
    6. *
    *
  8. *
  9. Lazy projections: all of the - many - transformations exposed by streams * that are annotated as {@link Projection} are lazy. Such methods do also work * with very large o potentially infinte streams. Methods not annotated that way * will not work on infinite streams, as they will never end * normally
  10. *
* * Streams provide messages for performing random access, * however they do not warrant to implement them in an efficient manner, * and it normally depends on the underlying source. * * Concrete, simple streams, collection handling-oriented, may be instantiated * through {@link Streams} class. Other concrete streams are be provided by * other staccato-commons libraries. * * Aside from these concrete streams, client code may also implement new ones. * In order to do that, it must not implement this interface * directly, but inherit from {@link AbstractStream}, which implements all * methods except of {@link #iterator()} * * * @author fbulgarelli * * @param * the type of object the stream is source of */ public interface Stream extends // ContainsAware, // Iterable, // ProtoMonad, Stream, A>, // SizeAware { // Iterable Thriterator iterator(); // ProtoMonad /** * Executes the given {@link Executable} block for each element. * * This message is equivalent to a for-each loop over this {@link Stream} * * @param block * @since 1.2 */ void forEach(@NonNull Executable block); /** * Maps the given side effect over this stream, by answering a {@link Stream} * that lazily applies the given side effect over each stream elements, and * retrieves them. * * @param block * @return {@code map(Functions.impure(block)} * @since 1.1 original version, replaced by {@link #forEach(Executable)} * @since 1.2 current version, incompatible with previous 1.1 * */ @Projection Stream each(@NonNull Executable block); /** * Transforms each element using the given function * * @param * @param function * the mapper used to transform each element, applying it * @return a new {@link Stream} projection that will retrieve the result of * applying the given function to each element */ @Projection Stream map(@NonNull Applicable function); /** * Preserves elements that satisfy the given predicate *

* Example: *

   *  //Answers stream [hello, world], which has only strings whose length is 5   
   *  Streams.cons("a", "hello", "world", "of", "streams", "!").filter(length().equal(5));
   * 
* * @param predicate * @return a new {@link Stream} projection that will retrieve only elements * that evaluate to true */ @Projection Stream
filter(@NonNull Evaluable predicate); /** * Preserves all elements but those that are equal to the given one. * * Equivalent to {@code filter(Predicates.equal(element).not())} * * @param element * @return a {@link Stream} that retrieves all elements that are not equal to * the given one */ @Projection Stream skip(@NonNull A element); // Specialized filtering /** * Preserves all elements while they satisfy the given predicate * * @param predicate * @return a new {@link Stream} projection that will retrieve all elements * from this stream, as long as none of them evaluates to false. */ @Projection Stream takeWhile(@NonNull Evaluable predicate); /** * Preserves up to N elements. It this Stream size is shorter than the given * amountOfElements, the resulting stream will retrieve the same * elements than this stream. * * @param amountOfElements * @return a new {@link Stream} projection that will retrieve up to N elements */ @Projection Stream take(@NotNegative int amountOfElements); /** * Discards all elements while they satisfy the given predicate * * @param predicate * @return a new {@link Stream} projection that will skip all elements as long * as they satisfy the given {@link Evaluable} */ @Projection Stream dropWhile(@NonNull Evaluable predicate); /** * Discards up to N elements from this {@link Stream}. Is the Stream size is * shorter than the given amountOfElements, the resulting stream * will be empty. * * @param amountOfElements * the amount of elements to discard * @return a new {@link Stream} that discards up to the given * amountOfElements */ @Projection Stream drop(@NotNegative int amountOfElements); /** * Answers a stream that is a substream of this one. The substream begins at * the specified {@code beginIndex}, and extends to the element at index * {@code endIndex} - 1, if it has enough elements, or up to its last element, * otherwise. *

* The resulting stream is always finite, and satisfies that * {@code size() <= endIndex - beginIndex} *

* As a particular case, if {@code beginIndex == endIndex}, an empty stream is * returned. *

* Examples: *
   *  Streams.from("hamburger").slice(4, 8).joinStrings(""); //answers "urge"
   *  Streams.from("smiles").slice(1, 5).joinStrings(""); //answers "mile"
   *  Streams.from("hello world!").slice(6, 309).joinStrings(""); //answers "world!"
   *  Streams.enumerate(1,20).slice(5,5).toList(); //answers []  
   *
* * @param beginIndex * the lower bound, inclusive * @param endIndex * the upper bound, exclusive * @return {@code drop(beginIndex).take(endIndex - beginIndex)} */ @Projection Stream
slice(@NotNegative int beginIndex, @NotNegative int endIndex); //Partitioning and splitting // TODO // Tuple2, Stream> splitBeforeIndex(@NotNegative int position); // // Tuple2, Stream> splitBefore(A element); // /*** * Splits stream elements into two lists using a predicate - elements that * evaluate to true will be returned in the first component, the rest will be * returned in the second component * * @param predicate * @return a new {@link Tuple2} that contains this stream partitioned into two * lists. */ @NonNull Tuple2, List> partition(@NonNull Evaluable predicate); /** * Splits stream elements into two ordered streams, that support random * access. This method just converts list returned by * {@link #partition(Evaluable)} into Streams. * * @param predicate * @return a new {@link Tuple2} that contains this stream partitioned into two * other streams. */ @NonNull Tuple2, Stream> streamPartition(@NonNull Evaluable predicate); // Specialized Mapping /** * Transforms each element using the given function. *

* Example: * *

 
   *  import static import net.sf.staccatocommons.util.Strings.*;
   *  //Answers [HELLO, WORLD, STREAMS]
   *  Streams.cons("hello", "world", "streams").map(toUpperCase());
   * 
* *
   * import static net.sf.staccatocommons.numbers.NumberTypes.*;
   *  ...
   * //answers Stream [6, 9, 11, 26]
   * Streams.cons(5, 8, 10, 25).map(add(1)).println(); 
   * 
* @param * @param function * the mapper used to transform each element, applying it * @return a new {@link Stream} projection that will retrieve the result of * applying the given function to each element */ @Projection Stream map(@NonNull Function function); // FlatMapping /** * Transformes each element into an iterable using the given function, and * concatenates (flattens) the result * * @param * @param function * @return a new {@link Stream} that will retrieve the result of transforming * each element and concatenating those transformations */ @Projection Stream flatMap(@NonNull Function> function); /** * Transformes each element into an array using the given function, and * concatenates (flattens) the result * * @param * @param function * @return a new {@link Stream} that will retrieve the result of transforming * each element and concatenating those trsansformations */ @Projection Stream flatMapArray(@NonNull Function function); // Reversing /** * Reverses this Stream, by returning a new Stream that retrieves elements in * the inverse order of this Stream. * * This may not be a {@link Projection}, depending on if the stream's source * permits it. * * @return a new {@link Stream} that retrieves elements in the inverse order * of this stream. */ @NonNull Stream
reverse(); // Searching /** * Returns the {@link #head()} of this {@link Stream} * * The different between {@link #head()} and {@link #any()} is strictly semantic: * use this message instead of {@link #head()} whenever the code needs an * unspecified element, rather than the first element of the stream. * * @return {@link #head()} * @throws EmptySourceException * if this {@link Stream} has no elements. */ A any() throws EmptySourceException; /** * Returns the {@link #head()} of the given {@link Stream}, just like {@link #any()}, * but as an option. If {@link Stream} has no elements, instead of throwing a * {@link EmptySourceException}, it returns {@link None} * * @return Option.some(element) if there is at least one element, * or Option.none(), otherwise. */ @NonNull Option anyOrNone(); /** * Shorthand for anyOrNone().valueOrNull() * * @return anyOrNone().valueOrNull() */ A anyOrNull(); /** * Shorthand for anyOrNone().valueOrElse(thunk) * * @param thunk * * @return anyOrNone().valueOrElse(thunk) */ A anyOrElse(@NonNull Thunk thunk); /** * Shorthand for anyOrNone().valueOrElse(value) * * @param value * @return anyOrNone().valueOrElse(value) */ A anyOrElse(A value); /** * Looks for a element that satisfies the given {@link Evaluable}. If such * element does not exist, throws {@link NoSuchElementException} * * @param predicate * @return the first elements that the predicate satisfies, if exists. * @throws EmptySourceException * if this stream is empty * @throws NoSuchElementException * if no element matches the predicate. */ A find(@NonNull Evaluable predicate) throws EmptySourceException, NoSuchElementException; /** * Looks for an element that satisfies the given {@link Evaluable}. If such * element exists, returns some(element). Otherwise, returns * {@link None}. * * @param predicate * @return None if no element matches the predicate, or some(element) if at * least one exists. As a particular case, this method will return * {@link None} if {@link Stream} is empty, regardless of the given * predicate */ @NonNull Option findOrNone(@NonNull Evaluable predicate); /** * Looks for an element that satisfies the given {@link Evaluable}. If such * element exists, returns it. Otherwise, returns null. * * @param predicate * @return null if no element matches the predicate, or an element that * satisfies it, if at least one exists. As a particular case, this * method will return null if {@link Stream} is empty, regardless of * the given predicate */ A findOrNull(@NonNull Evaluable predicate); /** * Looks for an element that satisfies the given {@link Evaluable}. If such * element exists, returns it. Otherwise, returns the given thunk's value. * * @param predicate * @return thunk.value() if no element matches the predicate, or * an element that satisfies it, if at least one exists. As a * particular case, this method will return the thunk's value if * {@link Stream} is empty, regardless of the given predicate */ A findOrElse(@NonNull Evaluable predicate, @NonNull Thunk thunk); /** * Looks for an element that satisfies the given {@link Evaluable}. If such * element exists, returns it. Otherwise, returns the given * element . * * @param predicate * @return findOrElse(predicate, Thunks.constant(element)) */ A findOrElse(@NonNull Evaluable predicate, @NonNull A element); // Testing /** * Tests if all elements satisfy the given {@link Evaluable} * * @param predicate * an {@link Evaluable} to evaluate each element * @return if all the elements evaluate to true */ boolean all(@NonNull Evaluable predicate); /** * Tests if all elements are equal * * @return if all the elements are equal */ boolean allEquiv(); /** * Tests if all elements are equivalent, using the given * equivTest * * @param equivTest * an {@link Evaluable2} used to testing if an element is equivalent * to another * @return if all the elements are equal */ boolean allEquivBy(Evaluable2 equivTest); /** * Tests if at least one element satisfies the given {@link Evaluable} * * @param predicate * an {@link Evaluable} to evaluate each element * @return if any element evaluate to true */ boolean any(@NonNull Evaluable predicate); /*** * Tests if any of the elements in this stream is contained in by the given * collection, using {@link Collection#contains(Object)} * * @param elements * @return if the intersection between this stream and the given elements is * not empty * @since 2.3 */ boolean intersects(Collection other); /*** * Tests if any of the elements in this stream is among the given elements * * @param elements * @return if the intersection between this stream and the given elements is not empty * @since 2.3 */ boolean intersects(A ... elements); /** * Test that the elements of this stream are equal to the elements of the * given array, and in the same order. * * @param elements * @return true if this stream has the same number of elements * that the given array, and each pair formed by elements of this * stream and the given array at same position are equal. * false otherwise */ boolean equiv(A... elements); /** * Test that the elements of this stream are equal to the elements of the * given {@link Iterable}, and in the same order. * * @param other * @return true if this stream has the same number of elements that * other, and each pair formed by elements of this * stream and given iterable at same position are equal. * false otherwise */ boolean equiv(Iterable other); /** * Test that the elements of this stream are equal to the elements of the * given {@link iterator}, and in the same order. * * @param iterable * @return true if this stream has the same number of elements that * other, and each pair formed by elements of this * stream and given iterable at same position are equal. * false otherwise * @since 2.2 */ boolean equiv(Iterator other); /** * Test that the elements of this stream are equivalent to the elements of the * given {@link Iterable}, and in the same order, using the given * equalityTest for determining equivalence between elements. * * @param equalityTest * @param iterable * * @return true if this stream has the same number of elements * that the given iterable, and each pair formed by * elements of this stream and given iterable at same * position satisfies the given {@link Evaluable2} */ boolean equivBy(@NonNull Evaluable2 equalityTest, @NonNull Iterable iterable); /** * Test that the elements of this stream are equivalent to the elements of the * given {@link Iterable}, and in the same order, using the given * equalityTest for determining equivalence between elements. * * @param equalityTest * @param iterable * * @return true if this stream has the same number of elements * that other, and each pair formed by * elements of this stream and other at same * position satisfies the given {@link Evaluable2} * @since 2.2 */ boolean equivBy(@NonNull Evaluable2 equalityTest, @NonNull Iterator other); /** * Test that the elements of this stream are equivalent to the given * elements, and in the same order, using the given * equalityTest for determining equivalence between elements. * * @param equalityTest * @param iterable * * @return true if this stream has the same number of elements * that the given elements, and each pair formed by * elements of this stream and given elements at same * position satisfies the given {@link Evaluable2} */ boolean equivBy(@NonNull Evaluable2 equalityTest, A... elements); /** * Test that the elements of this stream are equivalent to the elements of the * given {@link Iterable}, and in the same order, using the * Equiv.on(function) for determining equivalence between * elements. * * @param function * @param iterable * * @return true if this stream has the same number of elements * that the given iterable, and each pair formed by * elements of this stream and given iterable at same * position satisfies the {@link Evaluable2} * Equiv.on(function) */ boolean equivOn(@NonNull Applicable function, @NonNull Iterable iterable); /** * Test that the elements of this stream are equivalent to the elements of the * given {@link Iterator}, and in the same order, using the * Equiv.on(function) for determining equivalence between * elements. * * @param function * @param iterable * * @return true if this stream has the same number of elements * that the given {@link Iterator}, and each pair formed by * elements of this stream and given {@link Iterator} at same * position satisfies the {@link Evaluable2} * Equiv.on(function) * @since 2.2 */ boolean equivOn(@NonNull Applicable function, @NonNull Iterator other); /** * Test that the elements of this stream are equivalent to the given elements, * and in the same order, using the Equiv.on(function) for * determining equivalence between elements. * * @param function * @param iterable * * @return true if this stream has the same number of elements * that the given elements, and each pair formed by * elements of this stream and the given elements at same * position satisfies the {@link Evaluable2} * Equiv.on(function) */ boolean equivOn(@NonNull Applicable function, A... elements); // Folding /** * (Left)folds this {@link Stream} using an initial value and the given * two-arg function, producing a single aggregated result from all the Stream * elements. * * This consist of taking the initial value and a {@link Stream} element, * applying the function to them, and then repeating the process with this * result as the next initial value and the next element from the stream. The * last returned value is the folding result. * * @param * @param initial * @param function * @return the aggregates result * @see Folds */ B fold(B initial, @NonNull Applicable2 function); /** * (Left)folds the tail of this {@link Stream} using the first element of the * stream as initial value, producing a single aggregated result from all the * Stream elements. * * @param function * @return the folding result * @throws EmptySourceException * if this {@link Stream} is empty * @see #fold(Object, Applicable2) * @see Folds * */ A reduce(@NonNull Applicable2 function) throws EmptySourceException; /** * Answers the result of aggregating this stream using the given * reduction * * @param reduction * @return the folding result * @since 1.2 */ //TODO check exception here B reduce(Reduction reduction) throws NoSuchElementException; /** * (Left)folds this {@link Stream} concatenating each elements toString with a * separator * * @param separator * @return the string representation of each element concatenated using a * separator */ @NonNull String joinStrings(@NonNull String separator); /** * Answers the sum of the elements of this {@link Stream} using the given * {@link NumberType} * * @param numberType * @return the result of adding each element, or zero, if this stream is empty * @see Iterables#sum(Iterable, NumberType) */ @NonNull A sum(@NonNull NumberType numberType); /** * Answers the product of the elements of this {@link Stream} using the given * {@link NumberType} * * @param numberType * @return the result of multiplying each element, or one, if this stream is * empty * @see Iterables#product(Iterable, NumberType) */ @NonNull A product(@NonNull NumberType numberType); /** * Answers the average of the stream elements, using the given * {@link NumberType} for performing addition and division. * * @param numberType * @return the average of the stream elements * @throws ArithmeticException * if the stream is empty and number type does not support zero * division */ A average(@NonNull NumberType numberType) throws ArithmeticException; /** * Answers the number of element that satisfy the given predicate * * @param predicate * @return filter(predicate).size() * @since 2.1 */ int countOf(Evaluable predicate); // Sorting /** * Sorts this Stream, using their element's natural ordering * * @return a new {@link Stream} */ @Projection Stream sort(); /** * Sorts this Stream, using the given comparator * * @param comparator * @return a new {@link Stream} */ @Projection Stream sortBy(@NonNull Comparator comparator); /** * Sorts this Stream, using Compare.on(function) as comparator * * @param * @param function * @return a new {@link Stream} */ @Projection > Stream sortOn(Applicable function); /** * Answers the min element of the stream, using the given * comparator to compare elements. * * @param comparator * @return the minimum element. * @throws EmptySourceException * if the stream is empty. */ @NonNull A minimumBy(@NonNull Comparator comparator) throws EmptySourceException; /** * Answers the minimum element of the stream, using the given * Compare.on(function) to compare elements. * * @param function * @return the minimum element. * @throws EmptySourceException * if the stream is empty. */ > A minimumOn(@NonNull Applicable function) throws EmptySourceException; /** * Answers the minimum element of the stream, using elements natural order. * * @return the minimum element. * @throws EmptySourceException * if the stream is empty. * @throws ClassCastException * if elements are not comparable */ @NonNull A minimum() throws ClassCastException, EmptySourceException; /** * Answers the maximum element of the stream, using the given * comparator to compare elements. * * @param comparator * @return the maximum element. * @throws EmptySourceException * if the stream is empty. */ @NonNull A maximumBy(@NonNull Comparator comparator) throws EmptySourceException; /** * Answers the maximum element of the stream, using the given * Compare.on(function) to compare elements. * * @param function * @return the maximum element. * @throws EmptySourceException * if the stream is empty. */ > A maximumOn(@NonNull Applicable function) throws EmptySourceException; /** * Answers the maximum element of the stream, using elements natural order. * * @return the maximum element. * @throws EmptySourceException * if the stream is empty. * @throws ClassCastException * if elements are not comparable */ @NonNull A maximum() throws ClassCastException, EmptySourceException; // Appending /** * Equivalent to {@link #concat(Iterable)} * * @deprecated use {@link #concat(Iterable)} instead */ @Projection Stream append(@NonNull Iterable other); /** * Concatenates this with other * * It answers an {@link Stream} that retrieves elements from this Stream, and * then, after its last element, from the given iterable. * * As a particular case, if this Stream is infinite, the resulting Stream will * retrieve the same elements than this one. * * @param other * @return a new {@link Stream} * @since 2.2 */ @Projection Stream concat(@NonNull Iterable other); /** * Concatenates this with the given elements * * It answers an {@link Stream} that retrieves elements from this Stream, and * then, after its last element, the given elements. *

* As a particular case, if this Stream is infinite, the resulting Stream will * retrieve the same elements than this one. *

* Example: *

   * //answers the Stream [0, 1, 2, 3]
   * Streams.cons(0, 1).concat(2, 3); 
   * 
* * @param elements the element to add at the end of the stream * @return a new {@link Stream} * @since 2.2 */ @Projection Stream
concat(@NonNull A ... elements); /** * Concatenates this with the given {@link Iterator} * * It answers an {@link Stream} that retrieves elements from this Stream, and * then, after its last element, the given iterator's elements. * * As a particular case, if this Stream is infinite, the resulting Stream will * retrieve the same elements than this one. * * @param other the iterator whose elements will be added at the end of the stream * @return a new {@link Stream} * @since 2.2 */ Stream concat(@NonNull Iterator other); /** * Concatenates this Stream with the undefined Stream. Equivalent to * concat(Streams.undefined()) * * @return a new {@link Stream}, {@link Repeatable} as long as {@code this} is * repeatable * @see Streams#undefined() */ @Projection Stream appendUndefined(); /** * Adds an element as the last one of the stream. * * @param element * @return a new {@link Stream} that retrieves this {@link Stream} elements, * and then, the given element */ @Projection Stream append(A element); /** * Equivalent to {@link #delayedAppend(Thunk)}. * * @deprecated use {@link #delayedAppend(Thunk)} instead */ @Deprecated @Projection Stream append(@NonNull Thunk thunk); /** * Adds an element's thunk as the last one of the stream. * * @param thunk * @return a new {@link Stream} that retrieves this {@link Stream} elements, * and then, the value of the given thunk * @since 2.2 */ @Projection Stream delayedAppend(@NonNull Thunk thunk); /** * Adds an element as the first one of the stream. * * @param element * @return a new {@link Stream} that retrieves the given element, * and then, this {@link Stream} elements. */ @Projection Stream prepend(A element); /** * Equivalent to {@link #delayedPrepend(Thunk)} * * @deprecated use {@link #delayedPrepend(Thunk)} */ @Deprecated @Projection Stream prepend(@NonNull Thunk thunk); /** * Adds an element's thunk as the first one of the stream. * * @param thunk * @return a new {@link Stream} that retrieves the value of the given * thunk, and then, this {@link Stream} elements. */ @Projection Stream delayedPrepend(@NonNull Thunk thunk); // Inserting /** * Inserts {@code element} at {@code index - 1}. If stream has not enough * elements, that is, stream size is less than or equal to {@code index} * elements, the element is inserted at its end. *

* This message ensures that for any finite stream, and any element and index * *

   *  stream.insertBeforeIndex(element, index).containsBeforeIndex(element, index + 1)
   * 
* is true. *

* Examples: * *

   *  Streams.cons(4, 5, 6).insertBeforeIndex(0, 2); //answers [4, 5, 0, 6]
   *  Streams.repeat(1).take(4).insertBeforeIndex(0, 2); //answers [1, 1, 0, 1, 1]
   *  Streams.repeat(1).take(4).insertBeforeIndex(0, 20); //answers [1, 1, 1, 1, 0]
   * 
* * @param element the element to insert * @param index the index before inserting it * @return a {@link Stream} that lazily inserts the given element before the * given index * @since 2.2 */ Stream
insertBeforeIndex(A element, @NotNegative int index); /** * Inserts {@code element} before the first occurrence of {@code reference}. * If {@code reference} is not contained by this stream, the element is inserted at * its end. *

* This message ensures that for any finite stream, and any element and reference *

   *  stream.insertBefore(element, ref).containsBefore(element, ref)
   * 
* is true. *

* Examples: *

   *  Streams.cons('a', 'b', 'c').insertBefore('x', 'a'); //answers [x,a,b,c]
   *  Streams.cons('a', 'b', 'c').insertBefore('x', 'c'); //answers [a,b,x,c]
   *  Streams.cons('a', 'b', 'c').insertBefore('x', 'd'); //answers [a,b,c,x]
   * 
* * @param element * @param reference * @return a {@link Stream} that lazily inserts the given element before the * reference * @since 2.2 */ @Projection Stream
insertBefore(A element, A reference); // Branching /** * Answers a stream that retrieves a tuple per each element, formed by the * original element as the first component, and the result of applying the * given function to it as the second component. *

* This message is equivalent to {@code map(Tuples.clone(function))} *

* * @param function * the function to apply to each element * @return a new {@link Stream} * @see Tuples#clone(Applicable) * @since 1.2 */ @Projection Stream> clone(Applicable function); /** * Answers a Stream of pairs, where each one contains both results of applying * the given functions. Equivalent to * this.map(Tuples.branch(function0, function1)) * * @param * @param * @param function0 * @param function1 * @return a new {@link Stream} * @since 1.2 * @see Tuples#branch(Applicable, Applicable) */ @Projection Stream> branch(Applicable function0, Applicable function1); // Zipping /** * Returns a {@link Stream} formed by the result of applying the given * function to each pair of elements from this and * the given iterable. * * If either this or the given iterable is shorter than the other * given number of elements, the remaining elements of this are discarded * *

* Example: * *

   * //Answers the stream [1 + 4, 2 + 5] == [5, 7];
   * Streams.cons(1, 2).zipWith(integer().add(), 4, 5);  
   * 
* * @param elements * the elements to zip with this Stream * @param function * the function to apply to each pair * @return a new Stream which is the result of applying the given * {@link Applicable2} to each pair this Stream and the elements. The * resulting Stream size is the minimum of this size and the number of * elements * @see Iterables#zip(Iterable, Iterable) */ @Projection Stream zipWith(Function2 function, @NonNull B... elements); /** * Returns a {@link Stream} formed by the result of applying the given * function to each pair of elements from this and * the given iterable. * * If either this or the given iterable is shorter than * the other one, the remaining elements are discarded. * * @param * the type to the iterable to zip with this * {@link Stream} * @param * the resulting Stream element type * @param iterable * the {@link Iterable} to zip with this Stream * @param function * the function to apply to each pair * @return a new Stream formed applying the given {@link Applicable2} to each * pair this Stream and the given iterable. The resulting Stream size * is the minimum of both iterables sizes, or infinite, if both this * and iterable are * @see Iterables#zip(Iterable, Iterable) */ @Projection Stream zipWith(Function2 function, @NonNull Iterable other); /** * Returns a {@link Stream} formed by the result of applying the given * function to each pair of elements from this and * the other. * * If either this or the given {@link Iterator} is shorter than * the other one, the remaining elements are discarded. * * @param * the type to the iterable to zip with this * {@link Stream} * @param * the resulting Stream element type * @param other * the {@link Iterator} to zip with this Stream * @param function * the function to apply to each pair * @return a new Stream formed applying the given {@link Applicable2} to each * pair this Stream and the given iterator. The resulting Stream size * is the minimum of both iterables sizes, or infinite, if both this * and other are * @see Iterables#zip(Iterable, Iterable) * @since 2.2 */ Stream zipWith(Function2 function, @NonNull Iterator other); /** * Equivalent to {@link #zipWith(Function2, Iterable)}, with arguments * interchanged * * @deprecated use {@link #zipWith(Function2, Iterable)} */ @Deprecated @Projection Stream zip(@NonNull Iterable iterable, Function2 function); /** * Returns a {@link Stream} formed by by pair of element from * this and the given elements. * * If either this or the given array is shorter than the other * one, the remaining elements are discarded. *

* Examples: * *

   * //Answers the stream [(0, a), (1,b), (2,c)]
   * Streams.cons(0, 1, 2).zip('a', 'b', 'c');
   * 
* *
   * //Answers true
   * Streams 
   *   .from("hello")
   *   .zip(Streams.from("world!"))
   *   .equiv( 
   *     _('h', 'w'),
   *     _('e', 'o'),
   *     _('l', 'r'),
   *     _('l', 'l'),
   *     _('o', 'd')); //notice the last '!' was discarded
   * 
* * @param * @param iterable * @return a new Stream formed applying the given {@link Applicable2} to each * pair this Stream and the given elements. The resulting Stream size * is the minimum of both iterables sizes. * @see #zip(Iterable, Function2) * @since 2.2 */ @Projection Stream> zip(@NonNull B... elements); /** * Returns a {@link Stream} formed by by pair of element from * this and the given iterable. * * If either this or the given iterable is shorter than * the other one, the remaining elements are discarded. * * @param * @param iterable * @return a new Stream formed applying the given {@link Applicable2} to each * pair this Stream and the given iterable. The resulting Stream size * is the minimum of both iterables sizes, or infinite, if both this * and iterable are * @see Iterables#zip(Iterable, Iterable) * @see #zip(Iterable, Function2) */ @Projection Stream> zip(@NonNull Iterable iterable); /** * Returns a {@link Stream} formed by by pair of element from * this and the given {@link Iterator}. * * If either this or other is shorter than * the other one, the remaining elements are discarded. * * @param * @param other * @return a new Stream formed applying the given {@link Applicable2} to each * pair this Stream and the given iterator. The resulting Stream size * is the minimum of both iterables sizes, or infinite, if both this * and other are * @see Iterables#zip(Iterable, Iterable) * @see #zip(Iterable, Function2) * @since 2.2 */ Stream> zip(@NonNull Iterator other); // Printing /** * Prints the stream elements to an appendable, like {@link StringBuilder} or * a {@link Writer} * * @param destination * the appendable were print stream elements * @throws IOException * if any io error occurs */ void print(java.lang.Appendable destination) throws IOException; /** * Prints the stream elements to {@link System#out} * * @throws IOException * if any io error occurs */ void print(); /** * Prints the stream elements to an appendable, like {@link StringBuilder} or * a {@link Writer}, followed by a newline character * * @param destination * the appendable were print stream elements * @throws IOException * if any io error occurs */ void println(java.lang.Appendable o) throws IOException; /** * Prints the stream elements to {@link System#out}, followed by a newline * character. Equivalent to {@code println(System.out)} * * @throws IOException * if any io error occurs */ void println(); /** * Prints the stream elements to a string * * @return a string with the stream elements */ String printString(); // Copying /** * Converts this {@link Stream} into a Set, by adding all its elements to a * new Set. The resulting Set is {@link Serializable} and non-lazy. * * @return a new {@link Set} that contains all elements retrieved from this * {@link Stream} */ @NonNull Set
toSet(); /** * * Converts this {@link Stream} into a List, by adding all its elements to a * new List. The resulting List is {@link Serializable} and non-lazy. * * @return a new {@link List} that contains all elements retrieved from this * {@link Stream} */ @NonNull List toList(); /** * Creates a new array that has the same elements that the retrived by this * {@link Stream} * * @param clazz * the array component class * @return a new array */ @NonNull A[] toArray(@NonNull Class clazz); /** * Equivalent to {@link #memoize()} * * @deprecated the exact name of this concept is memoization, not * memorization. Use {@link #memoize()} instead */ @Deprecated @Repeatable @Projection Stream memorize(); /** * Memoizes stream elements and their order, by answering a lazy stream with * {@link Repeatable} iteration order that caches elements evaluated during * iteration. * * @return a new {@link Stream} that memoizes elements evaluated during * iteration * @since 2.2 */ @Repeatable @Projection Stream memoize(); // TODO // /** // * Memoizes the given // * number of initial stream elements and their order, by answering a lazy // * stream with {@link Repeatable} iteration order up to position // * {@code numberOfElements - 1} // * // * // * @param numberOfElements // * the number of initial elements to memoize. If this number is // * greather than stream size, all stream elements are memoized // * @return a new {@link Stream} that memoizes the first // * {@code numberOfElements} elements evaluated during iteration // * @since 2.3 // */ // Stream memoize(int numberOfElements); /** * Forces stream elements evaluation by converting it into a new ordered * stream one that is not lazy and that has repeatable iteration order. * * @return a new {@link Stream} that retrieves elements from the next * iteration of this Stream. */ @NonNull @Repeatable Stream force(); // Interscalating /** * Inserts the given element between each retrieved element of * this {@link Stream} * * @param element * @return a new {@link Stream} */ @Projection Stream intersperse(A element); /** * Inserts after each element the result of applying the given function to it. * For example: * *
   * Streams.cons(10, 9, 90).incorporate(integer().negate()).equiv(10, -10, 9, -9, 90, -90);
   * 
* * @param function * @return a new {@link Stream} * @since 1.2 */ @Projection Stream
incorporate(@NonNull Function function); /** * Inserts the given value after each element of the stream. * * This message is similar to {@link #intersperse(Object)}, but inserts the * value also at the end of the stream. * * @param element * Example: * *
   * Streams.cons('a', 'b', 'c').incorporate('d').equiv('a', 'd', 'b', 'd', 'c', 'd');
   * 
* * @return a new {@link Stream} * @since 1.2 */ @Projection Stream
incorporate(@NonNull A element); // Grouping /** * Groups elements by the given {@code groupingFunction}, and reduces each * group using the given {@code reduction}. *

* The grouping is performed so that two elements {@code a} and {@code b} will * be put in the same group if and only if * {@code groupFunction.apply(a).equals(groupFunction.apply(b)) } *

* * @param * @param groupFunction * @param reduction * @return a Map with an entry for each group, where its key is the result of * the grouping function, and the value is the result of the reduction * of the elements for that group */ @NonNull Map groupOn(Applicable groupFunction, Reduction reduction); // Cartesian product /** * Answers the Cartesian product of this stream and itself * * @param other * @return a new {@link Stream} projection * @see Iterables#cross(Iterable, Iterable) */ @Projection Stream> cross(); /** * Answers the Cartesian product of this stream and the given one * * @param * @param other * @return a new {@link Stream} projection * @see Iterables#cross(Iterable, Iterable) */ @Projection Stream> cross(@NonNull Stream other); /** * Answers the cartesian product of this {@link Stream} and the given * {@link Iterable} * * @param * @param other * @return cross(Streams.from(other)) * @see #cross(Stream) */ @Projection Stream> cross(@NonNull Iterable other); /** * Answers the cartesian product of this {@link Stream} and the given * elements. * * Example: * *
   * //Answers true
   * Streams
   *   .cons("male", "female")
   *   .cross("young", "middle-aged", "old")
   *   .equiv(
   *     _("male", "young"),
   *     _("male", "middle-aged"),
   *     _("male", "old"),
   *     _("female", "young"),
   *     _("female", "middle-aged"),
   *     _("female", "old"));
   * 
* * * @param * @param other * @return cross(Streams.cons(elements)) * @see #cross(Stream) * @since 2.2 */ Stream> cross(@NonNull B... elements); /** * Answers the cartesian product of this {@link Stream} and the given * {@link Iterator} * * @param * @param other * @return cross(Streams.from(other)) * @see #cross(Stream) * @since 2.2 */ @Projection Stream> cross(@NonNull Iterator other); /** * Answers the cartesian product of this {@link Stream} and each one of the * given streamOfStreams * * @param streamOfStreams * @return a new {@link Stream} projection */ @Projection Stream> crossStreams(@NonNull Stream> streamOfStreams); // Transforming whole stream /** * Lazily applies the given function to this {@link Stream}. * * @param * @param function * the function to apply to this stream * @return a new stream that will retrieve elements from the result of * applying the given function to this stream */ @Projection Stream transform(@NonNull Applicable, ? extends Stream> function); /** * Lazily applies the given function to this stream, * deconstructing this stream into head and tail, or into an empty stream. * * Unlike {@link Stream#transform(Applicable)}, whose function will receive * the whole stream, the given {@link DeconsApplicable}, when applied, will * take the head and tail of this {@link Stream}, if non empty, or no * arguments, if the stream is empty. * * @param * @param function * @return a new stream that will retrieve elements from the result of * applying the given function to this stream * @see #decons() */ @Projection Stream transform(@NonNull DeconsApplicable function); /** * Lazily applies the given function to this stream, * deconstructing this stream into a head thunk and tail, or into an empty * stream. * * Unlike {@link Stream#transform(Applicable)}, whose function will receive * the whole stream, the given {@link DeconsApplicable}, when applied, will * take a head's thunk and tail of this {@link Stream}, if non empty, or no * arguments, if the stream is empty. * * @param * @param function * @return a new stream that will retrieve elements from the result of * applying the given function to this stream * @see #delayedDecons() */ @Projection Stream transform(@NonNull DelayedDeconsApplicable function); // Accessing elements in ordered manner /** * Answers the first element. * * This is equivalent to {@link Stream#head()}. * * It is also equivalent to {@code get(0)}, but throws a * {@link EmptySourceException} if stream is empty * * @return {@link #head()} * @throws EmptySourceException * if there is no first element */ A first() throws EmptySourceException; /** * Answers the second element. This is equivalent to {@code get(1)}, but * throws a {@link NoSuchElementException} if stream {@code size < 2} * * @return {@code get(1)} * @throws NoSuchElementException * if there is no second element */ A second() throws NoSuchElementException; /** * Answers the third element. This is equivalent to {@code get(2)}, but throws * a {@link NoSuchElementException} if stream {@code size < 3} * * @return {@code get(2)} * @throws IndexOutOfBoundsException * if there is no third element */ A third() throws NoSuchElementException; /** * Answers the last element of this stream. This method only works with finite * streams * * @return the last element * @throws EmptySourceException */ A last() throws EmptySourceException; /** * Answers if both arguments are contained by this stream, and the first one * is before the second one. This method works even for stream that can be * iterated only once * * @param previous * @param next * @return whether both elements are contained by this {@link Stream}, and the * first is before the second one. * @see #containsBefore(Object, Object) */ boolean isBefore(A previous, A next); /** * Answers if {@code element} is contained by this stream, and its first * occurence is before the first occurence of the second one, if any. * *

* This message is similar to {@link #isBefore(Object, Object)}, but may be * true even if the {@code reference} is not present at the stream. It will be * always true if both element and reference are equal, too. *

* Examples: * *

   *  Streams.from("abcd").containsBefore('c', 'a'); //false. c is after a
   *  Streams.from("abcd").containsBefore('x', 'd'); //false. x is not present
   *  Streams.from("abcd").containsBefore('a', 'b'); //true
   *  Streams.from("abcd").containsBefore('b', 'd'); //true
   *  Streams.from("abcd").containsBefore('a', 'a'); //true
   *  Streams.from("abcd").containsBefore('x', 'x'); //false. x is not present
   * 
* * @param element * the element to test whether it is contained by this stream, and * appears before {@code reference} * @param reference * @return whether both elements are contained by this {@link Stream}, and the * first is before the second one. * @see #insertBefore(Object, Object) * @see #isBefore(Object, Object) * @since 2.2 */ boolean containsBefore(A element, A reference); /** * Answers if {@code element} is contained by this stream, and its first * occurence is before the given {@code index}. * * As a particular case, if {@code index} is 0, return always * false *

* Examples: * *

   *   Streams.from("abcd").containsBeforeIndex('x', 2); //false. x is not present
   *   Streams.from("abcd").containsBeforeIndex('c', 1); //false. c is present but at index 2
   *   Streams.from("abcd").containsBeforeIndex('a', 0); //false. a is present but at index 0
   *   Streams.from("abcd").containsBeforeIndex('a', 1); //true
   *   Streams.from("abcd").containsBeforeIndex('b', 3); //true
   *   Streams.from("abcd").containsBeforeIndex('b', 40); //true
   * 
* * @param element * @param index * @return whether elements is containted and before index * @since 2.2 * @see #insertBeforeIndex(Object, int) */ boolean containsBeforeIndex(A element, @NotNegative int index); /** * Answers the n-th element. * * @param n * @return the n-th element, zero based * @throws IndexOutOfBoundsException * if there is no n-th element, because stream has less than {@code n} elements */ A get(int n); /** * Answers the zero-based index of the given element * * @param element * @return the index of the element first element equal to {@code element}, or * -1, if it is not contained by this stream */ int indexOf(A element); /** * Answers the zero-based index of first element that matches the given * predicate * * @param predicate * @return the index of the first element that evaluates the {@code predicate} * to true, or -1, if no element satisfies it * @since 2.1 */ int findIndex(Evaluable predicate); /** * Answers a stream containing all the zero-based indices of the elements that * matches the given predicate * * @param predicate * @return a {@link Stream} with the indices of the elements that satisfy the * given predicate * @since 2.1 */ @Projection Stream indices(Evaluable predicate); /** * Answers the index of the given present element. This * method behaves exactly like {@link #indexOf(Object)}, with the only * difference that it will throw a {@link NoSuchElementException} if the given * element is not present on the stream * * @param element * @return the index of the given element * @throws NoSuchElementException * if the element is no contained by this {@link Stream} */ int positionOf(A element) throws NoSuchElementException; /** * Answers the zero-based index of first, present element * that matches the given predicate. This method behaves exactly like * {@link #findIndex(Evaluable)}, with the only difference that it will throw * a {@link NoSuchElementException} if the given element is not present on the * stream * * @param predicate * @return the index of the first element that evaluates the {@code predicate} * @throws NoSuchElementException * if no elements satisfies the given {@code predicate} * @since 2.1 */ int findPosition(Evaluable predicate) throws NoSuchElementException; /** * Preserves elements that whose index satisfy the given * predicate * * @param predicate * @return a new {@link Stream} projection that will retrieve only elements * whose index evaluate to true */ @Projection Stream
filterIndex(@NonNull Evaluable predicate); /** * Answers a streams that retrieves all the elements of this one, except of * that at the given index * * @param predicate * @return a new {@link Stream} that skips the element at the given index */ @Projection Stream skipIndex(int index); /*Deconstructtion */ /** * Answers this stream split into head and tail. * * This method is preferred over {@link #head()} and {@link #tail()}, as it * will work as expected even on non repeatable iteration streams. * * @return a pair containing the head and the tail of this stream. The tail is * {@link NonNull} and a {@link Projection}, but it is always * non-repeatable. * @throws EmptySourceException * if stream is empty */ @NonNull Tuple2> decons() throws EmptySourceException; /** * Answers this non-empty stream split into a head thunk and tail. * * This method is preferred over {@link #decons()} when the head value of the * {@link Stream} is potentially irrelevant, as this methods grants to suceeds * even in those cases where {@link #head()} fails. * * @return a pair containing a thunk that will provide the head, and the tail * of this stream. The tail is {@link NonNull} and a * {@link Projection}, but it is always non-repeatable. * @throws EmptySourceException * if stream is empty */ @NonNull Tuple2, Stream> delayedDecons() throws EmptySourceException; /** * Answers the head of the {@link Stream}, which is the first element of the * stream. However, if you need both head and tail in order to perfom * functional-style transformations over the stream, consider using * {@link #decons()}. * * @return {@link Stream#first()} * @throws EmptySourceException * if stream is empty */ A head() throws EmptySourceException; /** * Answers the tail of the {@link Stream} * * @return an {@link Stream} that retrieves all its elements, except of the * first one * @throws EmptySourceException * if stream is empty */ @Projection Stream tail() throws EmptySourceException; /** * @author flbulgarelli * @param */ public interface EmptyApplicable { /** * Applies this transformation when this Stream can not be deconstructed in * head and tail, because it is empty. * * @return the result of applying this transformation over and empty * {@link Stream} */ A emptyApply(); } /** * An {@link Applicable2} that can transform a {@link Stream} by * deconstructing it into head and tail, or into an empty stream. * * @author flbulgarelli * * @param * input stream type * @param * output stream type */ public interface DeconsApplicable extends Applicable2, Stream>, EmptyApplicable> { /** * Applies this transformation to a non empty Stream splitted into tail and * head. * * Independently of the original stream source, the tail Stream is always * non-repeatable. * * {@link Stream}s will send this message when evaluating * {@link Stream#transform(DeconsApplicable)} */ Stream apply(A head, Stream tail); } /** * An {@link Applicable2} that can transform a {@link Stream} by * deconstructing it into head thunk and tail, or into an empty stream. * * @author flbulgarelli * * @param * input stream type * @param * output stream type */ public interface DelayedDeconsApplicable extends Applicable2, Stream, Stream>, EmptyApplicable> { /** * Applies this transformation to a non empty Stream splitted into tail and * head's thunk. * * Independently of the original stream source, the tail Stream is always * non-repeatable. * * {@link Stream}s will send this message when evaluating * {@link Stream#transform(DeconsApplicable)} */ Stream apply(Thunk head, Stream tail); } }