Java SE 8 For the Really Impatient, Note 2
2,454 words in 15 minutes
Chapter 2 The Stream API
Processing collections of values and specifying what you want to have done, leaving the scheduling of operations to the implementation. E.g, compute the average of the values of a certain method.
Key points:
- Iterators imply a specific traversal strategy and prohibit efficient concurrent execution.
- You can create streams from collections, arrays, generators, or iterators.
- Use
filter
to select elements andmap
to transform elements. - Other operations for transforming streams include
limit
,distinct
, andsorted
. - To obtain a result from a stream, use a reduction operator such as
count
,max
,min
,findFirst
, orfindAny
. Some of these methods return anOptional
value. - The
Optional
type is intended as a safe alternative to working withnull
values. To use it safely, take advantage of theifPresent
andorElse
methods. - You can collect stream results in collections, arrays, strings or maps.
- The
groupingBy
andpartitioningBy
methods of theCollectors
class allow you to split the contents of a stream into groups, and to obtain a result for each group. - There are specialized streams for the primitive types,
int
,long
, anddouble
. - When you work with parallel streams, be sure to avoid side effects, and consider giving up ordering constraints.
- You need to be familiar with a small number of functional interfaces in order to use the stream library.
From Iteration to Stream Operations
Usually iterate over collection’s elements and do some work with each of them.
|
|
The stream
method yields a stream for the words
list. The filter
method returns another stream that contains only the words of length greater than twelve. The count
method reduces that stream to a result.
Differences between stream and collections
- Stream does not store its elements.
- Stream operations don’t mutate source. They return new streams that hold the reuslt.
- Stream operations are lazy when possible. Not executed until their result is needed.
Easily parallelized by changing stream
to parallelStream
What. not how principle: we describe what needs to be done, don’t specify in which order, or in which thread, this should happen.
Setup a pipeline of operations in 3 stages:
- Create a stream.
- Specify intermediate operations for transforming the initial stream into others
- Apply a terminal operation to produce a result.
Afterwards, the stream can no longer be used.
Stream operations are not executed on the elements in the order in which they are invoked on the streams. Nothing happens until count
is called. When the count
method asks for the first element, then the filter
method starts requesting elements, until it finds one that has length > 12.
Stream Creation
Turn any collection in to a stream with the stream
method that Java8 added to the Collection
interface
Use the static Stream.of
method for arrays
The of
method has a varargs parameters
Use Array.stream(array, from, to)
to make stream from a part of an array.
Use the static Stream.empty
method to make a stream with no elements
2 interfaces for making infinite streams:generate
takes a function with no arguments(or, an object of the Supplier<T>
interface). Whenever a stream value is needed, that function is called to produce a value
iterate
takes a seed value and a function(a UnaryOperator<T>
), and repeatedly applies the function to the previous result.
Pattern
class has a method splitAsStream
that splits a CharSequence
by a regular expression.
File.lines
method returns a Stream
of all lines in a file.
The stream and the underlying file with it will be closed when the try
block exits normally or through an exception.
The filter.map and flatMap Methods
filter
: yields a new stream with all elements that match a certain condition
The argument of filter
is a Predicate<T>
, that is, a function from T
to boolean
map
: transform the values in a stream in some way, a function is applied to each element.
Suppose you have
- a generic type
G
(such as Stream) - function
f
from some typeT
toG<U>
- function
g
fromU
toG<V>
Then you can compose them, that is, first f
and then g
, by using flatMap
.
|
|
In the above case, G
is Stream, T
is String, U
is Character, V
is also Character.
Extracting Substreams and Combining Streams
limit
: returns a new stream that ends after n elements(or when the original stream ends if it is shorter)
skip
: discards the first n elements
concat
: concatenate 2 streams
The first strema should not be infinite.
peek
: yields another stream with the same elements as the original, but a function is invoked every time an element is retrieved.
This way you can verify that the infinite stream returned by iterate is processed lazily.
Stateful Transformations
distinct
: yields elements from the original stream, in the same order, except that duplicates are suppressed. The stream must obviously remember the elements that it has already seen.
sorted
: must see the entire stream and sort it before it can give out any elements. You can’t sort an infinite stream. One for Comparable elements, the other accepts a Comparator. Useful when the sorting process is a part of a stream pipeline.
The Collections.sort
method sorts a collection in place, whereas Stream.sorted
returns a new sorted stream.