A [Stream](<https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html>) is a sequence of elements upon which sequential and parallel aggregate operations can be performed. Any given Stream can potentially have an unlimited amount of data flowing through it. As a result, data received from a Stream is processed individually as it arrives, as opposed to performing batch processing on the data altogether. When combined with lambda expressions they provide a concise way to perform operations on sequences of data using a functional approach.

Example: (see it work on Ideone)

Stream<String> fruitStream = Stream.of("apple", "banana", "pear", "kiwi", "orange");

fruitStream.filter(s -> s.contains("a"))
           .map(String::toUpperCase)
           .sorted()
           .forEach(System.out::println);

Output:

APPLE

BANANA

ORANGE

PEAR

The operations performed by the above code can be summarized as follows:

  1. Create a Stream<String> containing a sequenced ordered [Stream](<https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html>) of fruit String elements using the static factory method [Stream.of(values)](<https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html#of-T>...-).
  2. The [filter()](<https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html#filter-java.util.function.Predicate->) operation retains only elements that match a given predicate (the elements that when tested by the predicate return true). In this case, it retains the elements containing an "a". The predicate is given as a lambda expression.
  3. The [map()](<https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html#map-java.util.function.Function->) operation transforms each element using a given function, called a mapper. In this case, each fruit String is mapped to its uppercase String version using the method-reference [String::toUppercase](<https://docs.oracle.com/javase/8/docs/api/java/lang/String.html#toUpperCase-->).

Note that the map() operation will return a stream with a different generic type if the mapping function returns a type different to its input parameter. For example on a Stream<String> calling .map(String::isEmpty) returns a Stream<Boolean>

  1. The [sorted()](<https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html#sorted-->) operation sorts the elements of the Stream according to their natural ordering (lexicographically, in the case of String).
  2. Finally, the [forEach(action)](<https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html#forEach-java.util.function.Consumer->) operation performs an action which acts on each element of the Stream, passing it to a Consumer. In the example, each element is simply being printed to the console. This operation is a terminal operation, thus making it impossible to operate on it again.

Note that operations defined on the Stream are performed because of the terminal operation. Without a terminal operation, the stream is not processed. Streams can not be reused. Once a terminal operation is called, the Stream object becomes unusable.

http://i.stack.imgur.com/6p8aM.png

Operations (as seen above) are chained together to form what can be seen as a query on the data.


Closing Streams