Java Reference
In-Depth Information
Streams support lazy operations.
Streams can be ordered or unordered.
Streams cannot be reused.
The following sections will present brief snippets of code using streams. The code is meant to give you a feel for
the Streams API and to compare the Streams API with the Collections API. You do not need to understand the code
fully at this point. I will explain it later in detail.
Streams Have No Storage
A collection is an in-memory data structure that stores all its elements. All elements must exist in memory before they
are added to the collection. A stream has no storage; it does not store elements. A stream pulls elements from a data
source on-demand and passes them to a pipeline of operations for processing.
Infinite Streams
A collection cannot represent a group of infinite elements whereas a stream can. A collection stores all its elements in
memory, and therefore, it is not possible to have an infinite number of elements in a collection. Having a collection
of an infinite number of elements will require an infinite amount of memory and the storage process will continue
forever. A stream pulls its elements from a data source that can be a collection, a function that generates data, an I/O
channel, etc. Because a function can generate an infinite number of elements and a stream can pull data from it on
demand, it is possible to have a stream representing a sequence of infinite data elements.
Internal Iteration vs. External Iteration
Collections are based on external iteration. You obtain an iterator for a collection and process elements of the
collections in serial using the iterator. Suppose you have a list of integers from 1 to 5. You would compute the sum of
squares of all odd integers in the list as follows:
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
int sum = 0;
for (int n : numbers) {
if (n % 2 == 1) {
int square = n * n;
sum = sum + square;
}
}
The code uses a for-each loop that performs an external iteration on the list of integers. Simply put, the client
code (the for-loop in this case) pulls the elements out of collection and applies the logic to get the result.
Consider the following code that uses a stream to compute the sum of all odd integers in the same list:
int sum = numbers.stream()
.filter(n -> n % 2 == 1)
.map(n -> n * n)
.reduce(0, Integer::sum);
Did you notice the power and the simplicity of streams? You have replaced five statements with just one statement.
However, the code brevity is not the point that I want to make. The point is that you did not iterate over the elements
in the list when you used the stream. The stream did that for you internally. This is what I meant by internal iteration
 
Search WWH ::




Custom Search