What Is a Stream?
So what is a stream? Informally, you can think of it as a “fancy iterator” that supports database-like operations. Technically, a Stream is a sequence of elements supporting sequential and parallel bulk operations. Streams support lazy transformative operations (transforming a stream to another stream) such as
map, and consuming operations, such as
iterator. Once an operation has been performed on a stream, it is considered consumed and no longer usable for other operations.
However, streams don’t actually store elements; they’re computed on demand. Source Streams consume from a data-providing source such as collections, arrays, or I/O resources. Aggregate operations Streams support database-like operations and common operations from functional programming languages, such as
filter, map, reduce, findFirst, allMatch, sorted, and so on.
Furthermore, stream operations have two additional fundamental characteristics that differentiate them from collections: Pipelining Many stream operations return a stream themselves. This allows operations to be chained to form a larger pipeline. This style enables certain optimizations such as laziness, short-circuiting, and loop fusion. Internal iteration In contrast to collections, which are iterated explicitly (external iteration), stream operations do the iteration behind the scenes for you.
Stream operations are either intermediate or terminal. Intermediate operations return a stream so we can chain multiple intermediate operations without using semicolons. Terminal operations are either void or return a non-stream result. Consider the following Stream operation:
List<String> myList =
Arrays.asList("a1", "a2", "b1", "c2", "c1");
.filter(s -> s.startsWith("c"))
In the above example
sorted are intermediate operations whereas
forEach is a terminal operation.