Skip to content

Instantly share code, notes, and snippets.

@benjamin-bader
Created February 16, 2014 22:58
package com.keepsafe.services.manifest.collect;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
/**
* Represents a lazy, read-once stream of elements which may be filtered,
* transformed to different types, and consumed.
*
* <p>Streams differ from iterables in that where iterables provide sequential
* access to a collection, Streams are intended to be queried and transformed
* declaratively.</p>
*
* <p>Streams exist in two states - terminal and non-terminal. When a stream
* is non-terminal, query operations and transformations may be applied. When
* a termination operation is invoked, the stream is placed in a terminal
* state.</p>
*
* <p>>Non-terminal operations are those that do not immediately consume
* elements from the source stream, i.e. {@link Stream#map(Function)},
* {@link Stream#filter(Predicate)}, etc.</p>
*
* <p>Terminal operations are those that consume elements, such as
* {@link Stream#reduce(Object, Reducer)} and {@link Stream#single()}.</p>
*
* <p>This API is heavily cribbed from the Java 8 specification, with a healthy
* dose of LINQ for good measure. The implementation is entirely original, if
* not exactly novel.</p>
*
* @param <T> the type of element in the stream.
*
* @author ben
*/
public interface Stream<T> extends Iterable<T> {
/**
* Projects the current stream into a stream of type {@link R}.
* @param mapper a function mapping elements of type {@link T} to type {@link R}.
* @param <R> the type of element in the projected stream.
* @return the projected stream.
*/
<R> Stream<R> map(Function<T, R> mapper);
/**
* Filters a stream such that only elements satisfying the given
* {@code predicate} are included.
*
* @param predicate the predicate with which to filter the stream
* @return the filtered stream
*/
Stream<T> filter(Predicate<T> predicate);
/**
* Projects each element of the stream to a collection of type {@link R},
* and returns a stream of each such collection's elements in succession.
*
* <code>
* Stream&lt;String&gt; strs = Streams.of("foo", "bar");
* Function&lt;String, Iterable&lt;Char&gt;&gt; mapper = str -> str.getChars();
*
* strs.flatMap(mapper); // yields {'f', 'o', 'o', 'b', 'a', 'r'}
* </code>
* @param mapper
* @param <R>
* @return
*/
<R> Stream<R> flatMap(Function<T, Iterable<R>> mapper);
/**
* Takes the first N items of the stream
* @param count
* @return
*/
Stream<T> take(int count);
/**
* Casts each element of the stream to the given type {@link R}.
*
* <p>Use this at your own risk - due to type erasure, this is entirely
* unchecked and correctness is not enforced at compile-time.</p>
*
* @param <R> the type to cast each element
* @return a stream of type {@link R}
*/
<R> Stream<R> cast();
/**
* Extract and return the single element contained in the stream.
*
* <p>This is a terminal operation.</p>
*
* @return the single element in the stream.
* @throws NoSuchElementException when the stream does not contain exactly
* one element.
*/
T single() throws NoSuchElementException;
/**
* Returns the first element in the stream, or {@code null} if the stream
* is empty.
*
* <p>This is a terminal operation.</p>
*
* @return The first element, or {@code null}.
*/
T firstOrDefault();
/**
* Gathers the contents of the stream into a {@link List} and returns it.
*
* <p>This is a terminal operation.</p>
*
* @return the constructed list.
*/
List<T> toList();
/**
* Projects a stream into a {@link Map} based on the given key and value
* projectors.
*
* <p>This is a terminal operation.</p>
* @param keySelector a function that, given an element, will produce a
* map key.
* @param valueSelector a function that, given an element, will produce a
* map value.
* @param <K> the type of the map key
* @param <V> the type of the map value
* @return the constructed map.
*/
<K, V> Map<K, V> toMap(Function<T, K> keySelector, Function<T, V> valueSelector);
Set<T> toSet();
<R> Set<R> toSet(Function<T, R> mapper);
/**
* Applies a reducing operation to the stream, transforming its elements
* using the supplied {@link Reducer} for each element and returning the
* result.
*
* <p>This is a terminal operation.</p>
*
* @param seed The initial accumulator value
* @param reducer The reducing operation to apply
* @return the final accumulator value
*/
<A> A reduce(A seed, Reducer<A, T> reducer);
/**
* Append the given stream to the end of this stream.
* @param stream the stream to append
* @return the combined stream
*/
Stream<T> concat(Stream<T> stream);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment