Chapter 1: Streams
-Streams provide a view of data that lets you specify
computations at a higher conceptual level than collection
-Stream: specify what to have done, not how to do it.
-Example: Compute the average of certain property.
Specify the source of data and the property, and the
stream library can optimize the computation (by using
threads…)
1.1 From Iterating to Stream Operations
-Iterate and streams:
+The method names tell you right away what the code
intends to do.
+A stream is able to schedule the operations any way it
wants, as long as the result is correct. parrallelStream()
do in parallel.
-Streams follow the “what, now how” principle.
-A streams seems similar to a collection, but there are
significant differences:
-Workflow streams:
-API: p4
Stream:Filter(), count()
Collection: stream(), parallelStream()
1.2 Stream Creation
-Turn collection into a stream: stream()
-Turn array into a stream: static Stream.of()
+ : make a stream from a part of array
-Stream.empty(): make a stream with no element
-Stream interface has 2 static method for making infinite
streams:
+Stream.generate() : take an Supplier<T> interface
+Stream.iterate(): take an UnaryOperator<T> interface
-Stream.ofNullable(): make a stream from an object:
length 0 when object is null or length 1 otherwise.
-Note:
-Note:
+Turn an Iterable that is not a collection into a stream
+Iterator to stream:
-Caution: don’t modify the collection backing a stream
while carrying out a stream operation. Stream don’t
collect the data – the data is always in a separate
collection.
-API: p9
1.3 The filter, map, and flatMap Methods
-A stream transformation produces a stream whose
elements are derived from another stream
-filter(): Take a Predicate<T>
-map(): Pass a function
-flatMap(): concatenate result streams
1.4 Extracting Substreams and Combining
Streams
-Extract stream:
+limit(n): return a new stream that ends after n elements
+skip(n): the opposite
+takeWhile(predicate): take all elements from the
stream while the predicate is true, and then stop if it’s
false
+dropWhile(predicate): the opposite
-Combine: concat()
-API: p13
1.5 Other Stream Transformation
-distinct():
-sorted(): Comparable or Comparator interface
-peek(): same elements but a function is invoked every
time an element is retrieved. ->debugging
-Tip:
-API: p15
Distinct(), sorted(), peek()
1.6 Simple Reduction
-Reduction are terminal operations. They reduce the
stream to a nonstream value that can be used in program
+count(): return the number of elements of a stream
+max(), min(): return Opetional<T> value
+findFirst(): often useful when combined with filter
-Methods effective when parallelize the stream:
+findAny: combined with a filter
+anyMatch: if there is a match
+allMatch, noneMatch():
-Api: p16
1.7 The Optional Type
-Optional<T> object is a wrapper for either an object of
type T or no object. In the former case, we say that the
value is present.
1.7.1 Getting an Optional Value
-The key to use Optional is to use a method that either
produce an alternative if the value is not present, or
consumes the value only if it is present.
-Get a default where there was no match:
+Code to compute the default:
+Throw an exception:
-API: p17
orElse, orElseGet, orElseThrow
1.7.2 Consuming an Optional Value
-ifPresent(): accept a function
-ifPresentOrElse(): take one action if the Optional has a
value and another action if it doesn’t
API: p18
1.7.3 Pipelining Optional Values
-Another useful strategy is to keep the Optional intact.
+map(): transform the value inside an Optional
+filter(): consider Optional value that fulfill a certain
property before or after transform it
+or(): substitute an alternative Optional for an empty
Optional:
-API: p19 Optional: map, filter, or
1.7.4 How Not to Work with Optional Values
-API: p20 get(), orElseThrow(), isPresent()
1.7.5 Creating Optional Values
-Static methods Optional.of(result) and
Optional.empty()
-Optional.ofNullable(obj): returns Optional.of(obj) if obj
is not null and Optional.empty() otherwise.
1.7.6 Composing Optional Value Functions
with flatMap
-f() yield an Optional<T>, the type T has a method g
yields an Optional<U>. You could compose them by:
+You can repeat that process by a pipeline of steps,
chaining calls to flatMap:
1.7.7 Turning an Optional into a Stream
-Example: get a stream of users, skipping those IDs that
invalid:
+Each stream() return a stream with zero or one
element. flatMap() combines them all.
-Note: Suppose Users.classicLookup(id) returns a User
object or null, not an Optional<User>:
1.8 Collecting Results
-When you are done with a stream, you will often want
to look at the results. You can use iterator(), but
alternatively use forEach():
+forEach() traverses elements in arbitrary order. If you
want to process them in stream order, use
forEachOrdered()
-Usually, you want to collect the result in data structure.
Use toArray() to get an array of stream elements. It
returns Object[]. Pass in array constructor:
-For collecting stream elements to another target, use
collect() to take instance of Collector interface:
+Collector is an object that accumulates elements and
produces a result. Collectors class provides factory
methods:
+Collectors.toList(): collect stream into a list
+Collect into a set:
+Control which kind of set you get:
+Concatenate elements:
+Delimit between elements:
+If stream contains objects other than strings, 1st convert
them to string:
+To reduce stream results to a sum, count, average,
maximum, minimum; use
summarizing(Int/Long/Double). These methods take a
function that maps the stream objects to numbers and
yield a result of (Int/Long/Double)SummaryStatistics
type, simultaneously computing the sum, count, average,
maximum, minimum:
-API:p28
1.9 Collecting into Maps
-Collectors.toMap()
+When the values should be actual elements, use
Function.identity():
+If there is more one element with the same key, you can
supply a 3rd function argument that determines the value
for the key:
-Suppose we want to know all languages in a given
country. We need a Map<String, Set<String>>. At 1st, we
store a singleton set for each language. When a new
language is found, we form the union of the existing and
the new set.
+If you want a TreeMap, supply the constructor as 4th:
-API: p34
1.10 Grouping and Partitioning
-groupingBy(): form groups of values with the same
characteristics
+Group locales by country:
+Locale::getCountry() is the classifier function of the
grouping. You can look up all locales for a country code
+Note: each locale has a language code and a country
code. Some countries have multiple locales.
-When the classifier function is a predicate function, the
stream elements are partitioned into 2 lists: those
where the function returns true and the complement. It’s
efficient to use partitioningBy():
+groupingByConcurrent(): parallel stream.
1.11 Downstream Collectors
-groupingBy() yields a map whose values are lists. If you
want to process those lists in some way, supply a
downstream collector:
+Note: Java.util.stream.Collectors.*
-Several collectors reduce collected elements to numbers
+counting():
+summing(Int/Long/Double)
+maxBy, minBy
-collectingAndThen() collector add a final processing step
behind a collector.
-mapping(): Apply a function to each collected element
and pass the results to a downstream collector
+Gather a set of all language in a country
+flapMapping(): use with functions that return streams
-Collect elements into a summary statistics object if the
grouping or mapping function return int/long/double
-filtering collector:
-API: p40
1.12 Reduction Operations
-reduce() is a general mechanism for computing a value
from a stream.
-To use reduction with parallel streams, the operation
must be associative.
-Often, there is an identity as the start of the
computation:
+the identity value is returned if the stream is empty,
and you don’t need Optional class
-To operate of some property:
-Note: In practice, we won’t use reduce() a lot. See 1.13
-API: p43
1.13 Primitive Type Streams
-Stream library has specialized types IntStream,
LongStream (store short, char, byte, boolean),
DoubleStream(float, double) that store primitive values
directly, without using wrappers.
+You can also use generate() and iterate(). InStream and
LongStream have static range() and rangeClosed()
-CharSquenece interface has codePoint() and chars() that
yield an IntStream of Unicode codes of characters or
code units in UTF-16 encoding.
-You can transform stream of objects to primitive type
stream with mapToInt/Long/Double():
+boxed(): convert a primitive type stream to object
-Generally, primitive type stream methods are similar
with those on object streams. Some differences:
-Note: Random class have ints(), longs(), doubles() return
primitive type streams random numbers. Use
SplittableRandom class in parallel streams.
-API:p46
1.14 Parallel Streams
-Stream make it easy to parallelize bulk operations. The
process is mostly automatic.
-First, you must have a parallel stream from collection
with Collection.parallelStream():
+parallel() convert sequential into parallel:
-You need to ensure that any functions you pass to
parallel stream operations are safe to execute in parallel.
The best way to do that is to stay away from mutable
state (like group them)
-By default, streams that arise from ordered collection
are ordered. Some operations can be more effectively
parallelized when the ordering is dropped.
+.unordered.distinct()
+limit():
+Collectors.groupingByConcurrent(): the order will not
be the same as the stream order.
+You won’t care if you use a downstream collector that is
independent of ordering:
-Tip: If you process the lines of a huge file, parallelizing
the stream may improve performance.
-Note: By default, parallel stream use global fork-join
pool returned by ForkJoinPool.commonPool. To
substitute a different pool:
-API: p53
Parallel(), unordered(), parallelStream(),