SlideShare a Scribd company logo
#Devoxx
Java Lambda Stream
Master Class – Part 2
@StuartMarks @JosePaumard
#LambdaHOL#Devoxx
Stuart Marks
JDK Core Libraries Developer
Java Plaform Group, Oracle
Twitter: @stuartmarks
#LambdaHOL#Devoxx
@JosePaumard
https://www.youtube.com/user/JPaumard
https://www.slideshare.net/jpaumard
https://github.com/JosePaumard
#Devoxx #LambdaHOL
Questions?
#LambdaHOL
#LambdaHOL#Devoxx
Lambda/Streams Master Class 2
Setup
Map, Filter, FlatMap
Reduction, Function combination
Collectors.toMap()
Collectors.groupingBy()
Cascading Collectors
Streaming a Map
Streaming over Indexes
#LambdaHOL#Devoxx
Back to the Comparator
How to deal with null names?
Comparator<Person> cmp = Comparator.comparing(Person::getLastName)
.thenComparing(Person::getFirstName)
.thenComparing(Person::getAge);
#LambdaHOL#Devoxx
Back to the Comparator
In fact, this comparator:
Is equivalent to this one:
Comparator.comparing(Person::getLastName)
Comparator.comparing(Person::getLastName, Comparator.naturalOrder())
#LambdaHOL#Devoxx
Back to the Comparator
This allows this pattern:
So, to deal with null values:
Comparator.comparing(Person::getLastName,
Comparator.nullsLast(Comparator.naturalOrder()))
Comparator.comparing(Person::getLastName,
Comparator.comparing(String::length))
#LambdaHOL#Devoxx
Back to the Comparator
If we need to deal with null Person objects and
null names:
Comparator.nullsLast(
Comparator.comparing(Person::getLastName,
Comparator.nullsLast(Comparator.naturalOrder())
)
)
#Devoxx #LambdaHOL
Setup
#LambdaHOL#Devoxx
The LambdaHOL
You can find it here
https://github.com/stuart-marks/LambdaHOLv2
https://github.com/JosePaumard/lambda-master-class-part2
https://github.com/JosePaumard/lambda-master-class-part1
#LambdaHOL#Devoxx
Input Data — Alphabet
List<String> alphabet = List.of(
"alfa", "bravo", "charlie", "delta", "echo",
"foxtrot", "golf", "hotel", "india", "juliet",
"kilo", "lima", "mike", "november", "oscar",
"papa", "quebec", "romeo", "sierra", "tango",
"uniform", "victor", "whiskey", "x-ray", "yankee", "zulu");
#LambdaHOL#Devoxx
Input Data — Sonnet
List<String> sonnet = List.of(
"From fairest creatures we desire increase,",
"That thereby beauty's rose might never die,",
"But as the riper should by time decease,",
"His tender heir might bear his memory:",
"But thou contracted to thine own bright eyes,",
"Feed'st thy light's flame with self-substantial fuel,",
"Making a famine where abundance lies,",
"Thy self thy foe, to thy sweet self too cruel:",
"Thou that art now the world's fresh ornament,",
"And only herald to the gaudy spring,",
"Within thine own bud buriest thy content,",
"And, tender churl, mak'st waste in niggarding:",
"Pity the world, or else this glutton be,",
"To eat the world's due, by the grave and thee.");
#LambdaHOL#Devoxx
Helper Method — expand()
expand("abc") ⇒ ["a", "b", "c"]
List<String> expand(String s) {
return s.codePoints()
.mapToObj(Character::toString)
.collect(toList());
}
#Devoxx #LambdaHOL
Map, Filter using Streams
#LambdaHOL#Devoxx
Map, Filter Example
• From the Alphabet list
• Map to upper case
• Only keep the words with 6 letters
#LambdaHOL#Devoxx
Map, Filter Example
alphabet.stream()
.map(String::toUpperCase)
.filter(word -> word.length() == 6)
.forEach(System.out::println);
JULIET
QUEBEC
SIERRA
VICTOR
YANKEE
#Devoxx #LambdaHOL
FlatMap
#LambdaHOL#Devoxx
FlatMap
• Intermediate stream operation
• Consumes one element
• May produce zero or more elements
• Compare to map: consumes one, produces
one
• How is zero-or-more represented? A stream!
• T ⇒ Stream<R>
#LambdaHOL#Devoxx
FlatMap
Given a list of strings...
[alfa, bravo, charlie, ...]
expand each string to a list of one-letter strings
[ [a, l, f, a], [b, r, a, v, o], [c, h, ...] ... ]
but «flatten» the nesting structure
[a, l, f, a, b, r, a, v, o, c, h, ...]
#LambdaHOL#Devoxx
FlatMap
[[a, l, f, a], [b, r, a, v, o], [c, h, ...] ...]
List<List<String>> flatMap1() {
return alphabet.stream()
.map(word -> expand(word))
.collect(toList());
}
#LambdaHOL#Devoxx
FlatMap
[a, l, f, a, b, r, a, v, o, c, h, a, r, l, i, e, d, e, l, ...]
List<String> flatMap2() {
return alphabet.stream()
.flatMap(word -> expand(word).stream())
.collect(toList());
}
#LambdaHOL#Devoxx
FlatMap — Exercise
Split each line of the sonnet into words, and
then collect all the words into a single list.
To split a line into words, use
line.split(" +")
note: this returns an array, not a list or stream
#LambdaHOL#Devoxx
FlatMap — Solution
Split each line of the sonnet into words, and then
collect all the words into a single list.
[From, fairest, creatures, we, desire, increase, ...]
total 106 words
List<String> flatMapSolution() {
return sonnet.stream()
.flatMap(line -> Arrays.stream(line.split(" +")))
.collect(toList());
}
#Devoxx #LambdaHOL
Reduction
#LambdaHOL#Devoxx
Computing Factorials
Compute the factorial as a BigInteger using
streams and reduction
long number = 21;
// result is 51_090_942_171_709_440_000
#LambdaHOL#Devoxx
Computing Factorials
Compute the factorial as a BigInteger using
streams and reduction
long number = 21;
BigInteger result = LongStream.rangeClosed(1, 21)
.mapToObj(BigInteger::valueOf)
.reduce(BigInteger.ONE, BigInteger::multiply);
// result is 51_090_942_171_709_440_000
#Devoxx #LambdaHOL
Function Combination
#LambdaHOL#Devoxx
Function Combination
Suppose you have a shopping website where
the customer can apply a filter to limit the
products shown.
List<Product> show(Predicate<Product> predicate) {
return getAllProducts().stream()
.filter(predicate)
.collect(toList());
}
#LambdaHOL#Devoxx
Function Combination
Suppose you want the customer to be able to
apply two filters to the product list.
Now, how about three filters?
List<Product> show(Predicate<Product> p1, Predicate<Product> p2) {
return getAllProducts().stream()
.filter(p1.and(p2))
.collect(toList());
}
#LambdaHOL#Devoxx
Function Combination
Two predicates can be combined using the
Predicate.and() method.
This is all we need to write a method that
combines an arbitrary number of predicates.
Predicate<Product> p1 = ... ;
Predicate<Product> p2 = ... ;
Predicate<Product> combined = p1.and(p2);
#LambdaHOL#Devoxx
Function Combination
Reduction of a list over an operator applies that
operator between each element.
Predicate<Product> combine(List<Predicate<Product>> predicates) {
Predicate<Product> temp = product -> true;
for (Predicate<Product> cur : predicates) {
temp = temp.and(cur);
}
return temp;
}
#LambdaHOL#Devoxx
Function Combination
Reduction of a list over an operator applies that
operator between each element.
Predicate<Product> combine(List<Predicate<Product>> predicates) {
return predicates.stream()
.reduce(product -> true, Predicate::and);
}
#LambdaHOL#Devoxx
Function Combination
Now apply this to the original problem:
List<Product> show(List<Predicate<Product>> predicates) {
Predicate<Product> combinedPredicate = combine(predicates);
return getAllProducts().stream()
.filter(combinedPredicate)
.collect(toList());
}
#LambdaHOL#Devoxx
Function Combination — Exercise
An IntUnaryOperator is a functional interface that
takes an int and returns an int.
Write a method that combines an arbitrary sized
list of IntUnaryOperators into a single one.
Use streams and the IntUnaryOperator.andThen()
method.
Use your method to combine functions that add
one, multiply by two, and three.
#LambdaHOL#Devoxx
Function Combination — Exercise
IntUnaryOperator combine(List<IntUnaryOperator> operators) {
// TODO
}
IntUnaryOperator operator =
combine(List.of(i -> i + 1, i -> i * 2, i -> i + 3));
System.out.println(operator.applyAsInt(5));
15
#LambdaHOL#Devoxx
Function Combination — Solution
IntUnaryOperator combine(List<IntUnaryOperator> operators) {
return operators.stream()
.reduce(i -> i, IntUnaryOperator::andThen);
}
IntUnaryOperator operator =
combine(List.of(i -> i + 1, i -> i * 2, i -> i + 3));
System.out.println(operator.applyAsInt(5));
15
#Devoxx #LambdaHOL
Collectors.toMap()
#LambdaHOL#Devoxx
Collectors.toMap()
Collectors.toMap(keyFunction, valueFunction)
Takes each stream element
▪ runs the keyFunction to get a key
▪ runs the valueFunction to get a value
▪ enters computed (key, value) entries into the
result map
Returns the map as the final result
#LambdaHOL#Devoxx
Collectors.toMap()
Given the alphabet words, create a map whose
keys are the first letter and whose values are
the words.
Map<String, String> toMap1() {
return alphabet.stream()
.collect(toMap(word -> word.substring(0, 1),
word -> word));
}
#LambdaHOL#Devoxx
Collectors.toMap()
a => alfa
b => bravo
c => charlie
d => delta
e => echo
f => foxtrot
g => golf
h => hotel
i => india
j => juliet
k => kilo
l => lima
m => mike
n => november
o => oscar
#LambdaHOL#Devoxx
Collectors.toMap()
Now create the first-letter map using the
sonnet instead of the alphabet words.
Map<String, String> toMap1() {
return sonnet.stream()
.collect(toMap(word -> word.substring(0, 1),
word -> word));
}
#LambdaHOL#Devoxx
Collectors.toMap()
Exception in thread "main" java.lang.IllegalStateException: Duplicate key B (attempted merging values
But as the riper should by time decease, and But thou contracted to thine own bright eyes,)
at java.base/java.util.stream.Collectors.duplicateKeyException(Collectors.java:133)
at java.base/java.util.stream.Collectors.lambda$uniqKeysMapAccumulator$1(Collectors.java:180)
at java.base/java.util.stream.ReduceOps$3ReducingSink.accept(ReduceOps.java:169)
at java.base/java.util.AbstractList$RandomAccessSpliterator.forEachRemaining(AbstractList.java:720)
#LambdaHOL#Devoxx
Collectors.toMap()
The simple (two-arg) toMap() requires that all
keys be unique. Throws exception if duplicate
keys are encountered.
To handle this, a third arg mergeFunction can be
provided. It takes the values of the duplicate
keys and returns a merged value.
#LambdaHOL#Devoxx
Collectors.toMap()
Use a merge function that simply returns its
first argument. “First wins.”
Map<String, String> toMap3() {
return sonnet.stream()
.collect(toMap(line -> line.substring(0, 1),
line -> line,
(line1, line2) -> line1 // merge
));
}
#LambdaHOL#Devoxx
Collectors.toMap()
Eight of fourteen lines remain, so some
duplicates were lost.
P => Pity the world, or else this glutton be,
A => And only herald to the gaudy spring,
B => But as the riper should by time decease,
T => That thereby beauty's rose might never die,
F => From fairest creatures we desire increase,
W => Within thine own bud buriest thy content,
H => His tender heir might bear his memory:
M => Making a famine where abundance lies,
#LambdaHOL#Devoxx
Collectors.toMap()
Use a “last wins” merge function.
Map<String, String> toMap4() {
return sonnet.stream()
.collect(toMap(line -> line.substring(0, 1),
line -> line,
(line1, line2) -> line2 // merge
));
}
#LambdaHOL#Devoxx
Collectors.toMap()
Eight entries, but some are different.
P => Pity the world, or else this glutton be,
A => And, tender churl, mak'st waste in niggarding:
B => But thou contracted to thine own bright eyes,
T => To eat the world's due, by the grave and thee.
F => Feed'st thy light's flame with self-substantial fuel,
W => Within thine own bud buriest thy content,
H => His tender heir might bear his memory:
M => Making a famine where abundance lies,
#LambdaHOL#Devoxx
Collectors.toMap() — Exercise
Create a map from the lines of the sonnet, with
map keys being the first letter of the line, and
values being the line. For duplicate keys,
concatenate the lines with a newline in
between.
#LambdaHOL#Devoxx
Collectors.toMap() — Solution
Map<String, String> toMapSolution() {
return sonnet.stream()
.collect(
toMap(line -> line.substring(0, 1),
line -> line,
(line1, line2) ->
line1 + System.lineSeparator() + line2));
}
#LambdaHOL#Devoxx
Collectors.toMap() — Solution
P => Pity the world, or else this glutton be,
A => And only herald to the gaudy spring,
And, tender churl, mak'st waste in niggarding:
B => But as the riper should by time decease,
But thou contracted to thine own bright eyes,
T => That thereby beauty's rose might never die,
Thy self thy foe, to thy sweet self too cruel:
Thou that art now the world's fresh ornament,
To eat the world's due, by the grave and thee.
F => From fairest creatures we desire increase,
Feed'st thy light's flame with self-substantial fuel,
W => Within thine own bud buriest thy content,
H => His tender heir might bear his memory:
M => Making a famine where abundance lies,
#Devoxx #LambdaHOL
Collectors.groupingBy
#LambdaHOL#Devoxx
Collectors.groupingBy()
The groupingBy() collector is a fancy way of
collecting a map from a stream.
In its simplest form, it takes a classifier function
to transform each stream element into a key.
Map values are a list of stream elements
classified into the same key.
Stream<T> ⇒ Map<K, List<V>>
#LambdaHOL#Devoxx
Collectors.groupingBy()
From the alphabet words, create a map whose
keys are the word length, and whose values are
a list of those words. First start off with toMap().
Map<Integer, List<String>> groupingBy1() {
return alphabet.stream()
.collect(
toMap(
word -> word.length(),
word -> new ArrayList<>(Arrays.asList(word)),
(list1, list2) -> { list1.addAll(list2);
return list1; }));
}
#LambdaHOL#Devoxx
Collectors.groupingBy()
4 => [alfa, echo, golf, kilo, lima, mike, papa, zulu]
5 => [bravo, delta, hotel, india, oscar, romeo, tango, x-ray]
6 => [juliet, quebec, sierra, victor, yankee]
7 => [charlie, foxtrot, uniform, whiskey]
8 => [november]
#LambdaHOL#Devoxx
Collectors.groupingBy()
Change toMap() to groupingBy(). Same result!
Map<Integer, List<String>> groupingBy1() {
return alphabet.stream()
.collect(toMap(String::length,
s -> new ArrayList<>(Arrays.asList(s)),
(a, b) -> { a.addAll(b); return a; }));
}
Map<Integer, List<String>> groupingBy2() {
return alphabet.stream()
.collect(groupingBy(String::length));
}
#LambdaHOL#Devoxx
Collectors.groupingBy() — Exercise
Collect the lines of the sonnet into a map,
whose keys are the first letter of each line, and
whose values are a list of lines beginning with
that letter.
#LambdaHOL#Devoxx
Collectors.groupingBy() — Solution
Map<String, List<String>> groupingBySolution() {
return sonnet.stream()
.collect(groupingBy(line -> line.substring(0, 1)));
}
#LambdaHOL#Devoxx
Collectors.groupingBy() — Solution
P => [Pity the world, or else this glutton be,]
A => [And only herald to the gaudy spring,,
And, tender churl, mak'st waste in niggarding:]
B => [But as the riper should by time decease,,
But thou contracted to thine own bright eyes,]
T => [That thereby beauty's rose might never die,,
Thy self thy foe, to thy sweet self too cruel:,
Thou that art now the world's fresh ornament,,
To eat the world's due, by the grave and thee.]
F => [From fairest creatures we desire increase,,
Feed'st thy light's flame with self-substantial fuel,]
W => [Within thine own bud buriest thy content,]
H => [His tender heir might bear his memory:]
M => [Making a famine where abundance lies,]
#Devoxx #LambdaHOL
Cascading Collectors
#LambdaHOL#Devoxx
Cascading Collectors
The groupingBy() collector seems restrictive: it
collects stream elements into a list.
This behavior can be modified by providing a
“downstream” collector as another argument.
groupingBy(classifier, downstream)
#LambdaHOL#Devoxx
Collectors.counting()
A useful downstream collector is counting()
The counting() collector is analogous to
Stream.count().
#LambdaHOL#Devoxx
Collectors.counting()
The pattern is the following:
Map<String, Long> cascading2() {
return sonnet.stream()
.collect(groupingBy(line -> line.substring(0, 1),
Collectors.counting()));
}
#LambdaHOL#Devoxx
Collectors.counting()
P => 1L
A => 2L
B => 2L
T => 4L
F => 2L
W => 1L
H => 1L
M => 1L
#LambdaHOL#Devoxx
Collectors.mapping()
Another useful downstream collector is
mapping():
mapping(mapperFunction, downstream2)
The mapping() collector is analogous to
Stream.map(). It applies a mapper function to
an element and passes the result downstream
— to a second downstream collector.
#LambdaHOL#Devoxx
Collectors.mapping()
These are equivalent:
Map<String, List<String>> cascading2() {
return sonnet.stream()
.collect(
groupingBy(
line -> line.substring(0, 1),
mapping(line -> line, toList())
));
}
Map<String, List<String>> cascading1() {
return sonnet.stream()
.collect(groupingBy(line -> line.substring(0, 1)));
}
#LambdaHOL#Devoxx
Collectors.mapping()
The using mapping() as the downstream
collector enables:
▪ the stream elements collected into map values
can be transformed
▪ the transformed elements can be collected or
reduced differently
#LambdaHOL#Devoxx
Collectors.mapping()
Map<String, List<Integer>> cascading3() {
return sonnet.stream()
.collect(
groupingBy(
line -> line.substring(0, 1),
mapping(String::length, toList())
));
} P => [40]
A => [36, 46]
B => [40, 45]
T => [43, 46, 45, 46]
F => [42, 53]
W => [41]
H => [38]
M => [37]
#LambdaHOL#Devoxx
Cascading Collectors — Exercise
Group the lines of the sonnet by first letter, and
collect the first word of grouped lines into a set.
To extract the first word of a line, use
string.split(" +")[0]
#LambdaHOL#Devoxx
Cascading Collectors — Solution
Map<String, Set<Integer>> cascading3() {
return sonnet.stream()
.collect(
groupingBy(
line -> line.substring(0, 1),
mapping(line -> line.split(" +")[0], toSet())
));
} P => [Pity]
A => [And, And,]
B => [But]
T => [That, Thy, To, Thou]
F => [Feed'st, From]
W => [Within]
H => [His]
M => [Making]
#LambdaHOL#Devoxx
Cascading Collectors
A first set of collectors that need downstream
collectors to work:
- mapping()
- filtering()
- flatMapping()
Analogous to intermediate stream operations
#LambdaHOL#Devoxx
Cascading Collectors
A second set of collectors:
▪ joining()
▪ counting()
▪ groupingBy(), toMap(), toUnmodifiableMap()
▪ toList(), toSet(), toUnmodifiableList() (and set)
▪ reducing()
Analogous to terminal stream operations
#LambdaHOL#Devoxx
Cascading Collectors
Group lines of the sonnet by first letter, and
collect the grouped lines into a single string
separated by newlines.
Map<String, String> cascading4() {
return sonnet.stream()
.collect(groupingBy(line -> line.substring(0, 1),
joining("n")
)
);
}
#LambdaHOL#Devoxx
Cascading Collectors
P => Pity the world, or else this glutton be,
A => And only herald to the gaudy spring,
And, tender churl, mak'st waste in niggarding:
B => But as the riper should by time decease,
But thou contracted to thine own bright eyes,
T => That thereby beauty's rose might never die,
Thy self thy foe, to thy sweet self too cruel:
Thou that art now the world's fresh ornament,
To eat the world's due, by the grave and thee.
F => From fairest creatures we desire increase,
Feed'st thy light's flame with self-substantial fuel,
W => Within thine own bud buriest thy content,
H => His tender heir might bear his memory:
M => Making a famine where abundance lies,
#LambdaHOL#Devoxx
Cascading Collectors — Exercise
Generate a frequency table of letters in the
sonnet. Remember the expand() helper
method.
Hints: use flatMap(), groupingBy(), and
counting().
#LambdaHOL#Devoxx
Cascading Collectors — Solution
Map<String, Long> cascadingSolution2() {
return sonnet.stream()
.flatMap(line -> expand(line).stream())
.collect(groupingBy(ch -> ch, counting()));
}
A => 2
B => 2
F => 2
H => 1
M => 1
P => 1
T => 4
W => 1
=> 92
a => 28
b => 11
c => 9
d => 20
e => 68
f => 9
g => 12
' => 6
h => 33
i => 29
k => 2
l => 18
, => 15
- => 1
m => 10
. => 1
n => 29
o => 25
p => 2
r => 33
s => 30
t => 54
u => 17
v => 2
w => 11
y => 14
: => 3
#Devoxx #LambdaHOL
Streaming a Map
#LambdaHOL#Devoxx
Streaming a Map
Find the most frequently occurring word from
the Sonnet
- 1st step: find one of those words
- 2nd step: find all those words in a list
#LambdaHOL#Devoxx
Streaming a Map
Two hints:
1) You cannot stream a map. To stream a map,
you need to get a stream of entries from its
entrySet().
Stream<Map.Entry<K, V>> stream =
map.entrySet().stream();
#LambdaHOL#Devoxx
Streaming a Map
Two hints:
2) There is a Stream.max() method
And Map.Entry provides comparators
stream.max(comparator)
.orElseThrow(); // max returns an Optional
stream.max(Map.Entry.comparingByValue())
.orElseThrow(); // max returns an Optional
#LambdaHOL#Devoxx
Inverting a Map
Suppose there are multiple maximum values
Max finds one of them
Finding all of them can be done by
converting a Map<word, count>
to a Map<count, List<word>>
#Devoxx #LambdaHOL
Streaming Over Indexes
#LambdaHOL#Devoxx
Streaming Over Indexes
Sometimes you need to process groups of
adjacent elements or a “sliding window” of
elements from a stream. The usual way of
streaming elements doesn’t handle this well.
If you have the elements in an array or random-
access list, you can work around this limitation
by streaming indexes instead of elements.
#LambdaHOL#Devoxx
Streaming Over Indexes
Split into sublists of size N adjacent elements:
N=3:
List<List<String>> streamIndexes1(int N) {
int SIZE = alphabet.size();
return IntStream.range(0, SIZE/N)
.mapToObj(i -> alphabet.subList(N*i, N*(i+1)))
.collect(toList());
}
[[alfa, bravo, charlie], [delta, echo, foxtrot], [golf, hotel, india],
[juliet, kilo, lima], [mike, november, oscar], [papa, quebec, romeo],
[sierra, tango, uniform], [victor, whiskey, x-ray]]
#LambdaHOL#Devoxx
Streaming Over Indexes
Adjust ranges and protect bounds with min():
List<List<String>> streamIndexes2(int N) {
int SIZE = alphabet.size();
return IntStream.range(0, (SIZE+N-1)/N)
.mapToObj(i -> alphabet.subList(N*i, Math.min(SIZE, N*(i+1))))
.collect(toList());
}
[[alfa, bravo, charlie], [delta, echo, foxtrot], [golf, hotel, india],
[juliet, kilo, lima], [mike, november, oscar], [papa, quebec, romeo],
[sierra, tango, uniform], [victor, whiskey, x-ray], [yankee, zulu]]
#LambdaHOL#Devoxx
Streaming Over Indexes
Alternatively, use rangeClosed():
List<List<String>> streamIndexes2(int N) {
int SIZE = alphabet.size();
return IntStream.rangeClosed(0, (SIZE+N-1)/N)
.mapToObj(i -> alphabet.subList(N*i, Math.min(SIZE, N*(i+1))))
.collect(toList());
}
[[alfa, bravo, charlie], [delta, echo, foxtrot], [golf, hotel, india],
[juliet, kilo, lima], [mike, november, oscar], [papa, quebec, romeo],
[sierra, tango, uniform], [victor, whiskey, x-ray], [yankee, zulu]]
#LambdaHOL#Devoxx
Streaming Over Indexes — Exercise
From the alphabet list, produce a list of
overlapping sublists of length N (sliding
window)
[[alfa, bravo, charlie], [bravo, charlie, delta], [charlie, delta,
echo], [delta, echo, foxtrot], [echo, foxtrot, golf], ...
#LambdaHOL#Devoxx
Streaming Over Indexes — Solution
One solution:
[[alfa, bravo, charlie], [bravo, charlie, delta], [charlie, delta,
echo], [delta, echo, foxtrot], [echo, foxtrot, golf], ...
List<List<String>> streamIndexesSolution1(int N) {
int SIZE = alphabet.size();
return IntStream.range(0, SIZE-N+1)
.mapToObj(i -> alphabet.subList(i, i+N))
.collect(toList());
}
#LambdaHOL#Devoxx
Streaming Over Indexes — Solution
Variation:
[[alfa, bravo, charlie], [bravo, charlie, delta], [charlie, delta,
echo], [delta, echo, foxtrot], [echo, foxtrot, golf], ...
List<List<String>> streamIndexesSolution2(int N) {
int SIZE = alphabet.size();
return IntStream.rangeClosed(N, SIZE)
.mapToObj(i -> alphabet.subList(i-N, i))
.collect(toList());
}
#LambdaHOL#Devoxx
Streaming Over Indexes — Exercise 2
Split the alphabet list into runs (sublists) of
strings of non-decreasing length, preserving
order.
That is, within each sublist, the next string
should always be the same length or longer.
[[alfa, bravo, charlie], [delta], [echo, foxtrot], [golf, ...] ...]
#LambdaHOL#Devoxx
Streaming Over Indexes — Solution 2
Insight: a new sublist starts when this string is
shorter than the previous string. Find the
indexes where this occurs.
[3, 4, 6, 10, 14, 15, 17, 19, 21, 23, 25]
List<Integer> breaks =
IntStream.range(1, alphabet.size())
.filter(i -> alphabet.get(i).length() <
alphabet.get(i-1).length())
.boxed()
.collect(toList());
#LambdaHOL#Devoxx
Streaming Over Indexes — Solution 2
We want sublists between these breaks. Run a
stream over the breaks to generate sublists.
[[delta], [echo, foxtrot], [golf, hotel, india, juliet], [kilo, lima,
mike, november], [oscar], [papa, quebec], [romeo, sierra], [tango,
uniform], [victor, whiskey], [x-ray, yankee]]
List<List<String>> sublists =
IntStream.range(0, breaks.size()-1)
.mapToObj(i -> alphabet.subList(breaks.get(i),
breaks.get(i+1)))
.collect(toList());
#LambdaHOL#Devoxx
Streaming Over Indexes — Solution 2
Add starting and ending indexes to break list to
pick up leading and trailing sublists.
[[alfa, bravo, charlie], [delta], [echo, foxtrot], [golf, hotel, india,
juliet], [kilo, lima, mike, november], [oscar], [papa, quebec], [romeo,
sierra], [tango, uniform], [victor, whiskey], [x-ray, yankee], [zulu]]
breaks.add(0, 0);
breaks.add(alphabet.size());
List<List<String>> sublists =
IntStream.range(0, breaks.size()-1)
.mapToObj(i -> alphabet.subList(breaks.get(i),
breaks.get(i+1)))
.collect(toList());
#LambdaHOL#Devoxx
Streaming Over Indexes — Solution 2
List<Integer> breaks =
IntStream.range(1, alphabet.size())
.filter(i -> alphabet.get(i).length() <
alphabet.get(i-1).length())
.boxed()
.collect(toList());
breaks.add(0, 0);
breaks.add(alphabet.size());
List<List<String>> sublists =
IntStream.range(0, breaks.size()-1)
.mapToObj(i -> alphabet.subList(breaks.get(i),
breaks.get(i+1)))
.collect(toList());
#LambdaHOL#Devoxx
Streaming Over Indexes — Solution 2
[[alfa, bravo, charlie], [delta], [echo, foxtrot], [golf, hotel, india,
juliet], [kilo, lima, mike, november], [oscar], [papa, quebec], [romeo,
sierra], [tango, uniform], [victor, whiskey], [x-ray, yankee], [zulu]]
#Devoxx
Questions?
@StuartMarks @JosePaumard
#LambdaHOL
https://github.com/JosePaumard/lambda-master-class-part1
https://github.com/JosePaumard/lambda-master-class-part2

More Related Content

What's hot

Advanced Javascript
Advanced JavascriptAdvanced Javascript
Advanced JavascriptAdieu
 
jpa-hibernate-presentation
jpa-hibernate-presentationjpa-hibernate-presentation
jpa-hibernate-presentationJohn Slick
 
Hibernate
HibernateHibernate
Hibernate
Prashant Kalkar
 
07 java collection
07 java collection07 java collection
07 java collection
Abhishek Khune
 
Laravel Design Patterns
Laravel Design PatternsLaravel Design Patterns
Laravel Design Patterns
Bobby Bouwmann
 
Java 8 Lambda and Streams
Java 8 Lambda and StreamsJava 8 Lambda and Streams
Java 8 Lambda and Streams
Venkata Naga Ravi
 
From Java 11 to 17 and beyond.pdf
From Java 11 to 17 and beyond.pdfFrom Java 11 to 17 and beyond.pdf
From Java 11 to 17 and beyond.pdf
José Paumard
 
Functional programming with Java 8
Functional programming with Java 8Functional programming with Java 8
Functional programming with Java 8
LivePerson
 
Java Collections | Collections Framework in Java | Java Tutorial For Beginner...
Java Collections | Collections Framework in Java | Java Tutorial For Beginner...Java Collections | Collections Framework in Java | Java Tutorial For Beginner...
Java Collections | Collections Framework in Java | Java Tutorial For Beginner...
Edureka!
 
Java 8 streams
Java 8 streamsJava 8 streams
Java 8 streams
Manav Prasad
 
Major Java 8 features
Major Java 8 featuresMajor Java 8 features
Major Java 8 features
Sanjoy Kumar Roy
 
How Hashmap works internally in java
How Hashmap works internally  in javaHow Hashmap works internally  in java
How Hashmap works internally in java
Ramakrishna Joshi
 
Hibernate presentation
Hibernate presentationHibernate presentation
Hibernate presentation
Manav Prasad
 
Spring I/O 2012: Natural Templating in Spring MVC with Thymeleaf
Spring I/O 2012: Natural Templating in Spring MVC with ThymeleafSpring I/O 2012: Natural Templating in Spring MVC with Thymeleaf
Spring I/O 2012: Natural Templating in Spring MVC with Thymeleaf
Thymeleaf
 
Spring boot
Spring bootSpring boot
Spring boot
sdeeg
 
Java 8 lambda expressions
Java 8 lambda expressionsJava 8 lambda expressions
Java 8 lambda expressions
Logan Chien
 
Capabilities for Resources and Effects
Capabilities for Resources and EffectsCapabilities for Resources and Effects
Capabilities for Resources and Effects
Martin Odersky
 
Java 8 - Features Overview
Java 8 - Features OverviewJava 8 - Features Overview
Java 8 - Features Overview
Sergii Stets
 
Java Lambda Expressions.pptx
Java Lambda Expressions.pptxJava Lambda Expressions.pptx
Java Lambda Expressions.pptx
SameerAhmed593310
 
REST APIs with Spring
REST APIs with SpringREST APIs with Spring
REST APIs with Spring
Joshua Long
 

What's hot (20)

Advanced Javascript
Advanced JavascriptAdvanced Javascript
Advanced Javascript
 
jpa-hibernate-presentation
jpa-hibernate-presentationjpa-hibernate-presentation
jpa-hibernate-presentation
 
Hibernate
HibernateHibernate
Hibernate
 
07 java collection
07 java collection07 java collection
07 java collection
 
Laravel Design Patterns
Laravel Design PatternsLaravel Design Patterns
Laravel Design Patterns
 
Java 8 Lambda and Streams
Java 8 Lambda and StreamsJava 8 Lambda and Streams
Java 8 Lambda and Streams
 
From Java 11 to 17 and beyond.pdf
From Java 11 to 17 and beyond.pdfFrom Java 11 to 17 and beyond.pdf
From Java 11 to 17 and beyond.pdf
 
Functional programming with Java 8
Functional programming with Java 8Functional programming with Java 8
Functional programming with Java 8
 
Java Collections | Collections Framework in Java | Java Tutorial For Beginner...
Java Collections | Collections Framework in Java | Java Tutorial For Beginner...Java Collections | Collections Framework in Java | Java Tutorial For Beginner...
Java Collections | Collections Framework in Java | Java Tutorial For Beginner...
 
Java 8 streams
Java 8 streamsJava 8 streams
Java 8 streams
 
Major Java 8 features
Major Java 8 featuresMajor Java 8 features
Major Java 8 features
 
How Hashmap works internally in java
How Hashmap works internally  in javaHow Hashmap works internally  in java
How Hashmap works internally in java
 
Hibernate presentation
Hibernate presentationHibernate presentation
Hibernate presentation
 
Spring I/O 2012: Natural Templating in Spring MVC with Thymeleaf
Spring I/O 2012: Natural Templating in Spring MVC with ThymeleafSpring I/O 2012: Natural Templating in Spring MVC with Thymeleaf
Spring I/O 2012: Natural Templating in Spring MVC with Thymeleaf
 
Spring boot
Spring bootSpring boot
Spring boot
 
Java 8 lambda expressions
Java 8 lambda expressionsJava 8 lambda expressions
Java 8 lambda expressions
 
Capabilities for Resources and Effects
Capabilities for Resources and EffectsCapabilities for Resources and Effects
Capabilities for Resources and Effects
 
Java 8 - Features Overview
Java 8 - Features OverviewJava 8 - Features Overview
Java 8 - Features Overview
 
Java Lambda Expressions.pptx
Java Lambda Expressions.pptxJava Lambda Expressions.pptx
Java Lambda Expressions.pptx
 
REST APIs with Spring
REST APIs with SpringREST APIs with Spring
REST APIs with Spring
 

Similar to Lambdas and Streams Master Class Part 2

Hadoop and HBase experiences in perf log project
Hadoop and HBase experiences in perf log projectHadoop and HBase experiences in perf log project
Hadoop and HBase experiences in perf log project
Mao Geng
 
Java gets a closure
Java gets a closureJava gets a closure
Java gets a closure
Tomasz Kowalczewski
 
Java 8 Workshop
Java 8 WorkshopJava 8 Workshop
Java 8 Workshop
Mario Fusco
 
New Features in JDK 8
New Features in JDK 8New Features in JDK 8
New Features in JDK 8
Martin Toshev
 
Lambdas and Laughs
Lambdas and LaughsLambdas and Laughs
Lambdas and Laughs
Jim Bethancourt
 
Intro to Reactive Thinking and RxJava 2
Intro to Reactive Thinking and RxJava 2Intro to Reactive Thinking and RxJava 2
Intro to Reactive Thinking and RxJava 2
JollyRogers5
 
Lecture 2 part 3
Lecture 2 part 3Lecture 2 part 3
Lecture 2 part 3
Jazan University
 
Java 8
Java 8Java 8
Java 8
vilniusjug
 
New features in jdk8 iti
New features in jdk8 itiNew features in jdk8 iti
New features in jdk8 iti
Ahmed mar3y
 
Introduction to Map-Reduce Programming with Hadoop
Introduction to Map-Reduce Programming with HadoopIntroduction to Map-Reduce Programming with Hadoop
Introduction to Map-Reduce Programming with Hadoop
Dilum Bandara
 
Java 8 by example!
Java 8 by example!Java 8 by example!
Java 8 by example!
Mark Harrison
 
Refactoring to Macros with Clojure
Refactoring to Macros with ClojureRefactoring to Macros with Clojure
Refactoring to Macros with ClojureDmitry Buzdin
 
Stata Programming Cheat Sheet
Stata Programming Cheat SheetStata Programming Cheat Sheet
Stata Programming Cheat Sheet
Laura Hughes
 
Stata cheatsheet programming
Stata cheatsheet programmingStata cheatsheet programming
Stata cheatsheet programming
Tim Essam
 
Python - Lecture 12
Python - Lecture 12Python - Lecture 12
Python - Lecture 12
Ravi Kiran Khareedi
 
Java 8 stream and c# 3.5
Java 8 stream and c# 3.5Java 8 stream and c# 3.5
Java 8 stream and c# 3.5
Quang Trần Duy
 
Matlab Functions
Matlab FunctionsMatlab Functions
Matlab Functions
Umer Azeem
 
Java 8 Intro - Core Features
Java 8 Intro - Core FeaturesJava 8 Intro - Core Features
Java 8 Intro - Core Features
GlobalLogic Ukraine
 
Hadoop - Introduction to mapreduce
Hadoop -  Introduction to mapreduceHadoop -  Introduction to mapreduce
Hadoop - Introduction to mapreduce
Vibrant Technologies & Computers
 
Hadoop ecosystem
Hadoop ecosystemHadoop ecosystem
Hadoop ecosystem
Ran Silberman
 

Similar to Lambdas and Streams Master Class Part 2 (20)

Hadoop and HBase experiences in perf log project
Hadoop and HBase experiences in perf log projectHadoop and HBase experiences in perf log project
Hadoop and HBase experiences in perf log project
 
Java gets a closure
Java gets a closureJava gets a closure
Java gets a closure
 
Java 8 Workshop
Java 8 WorkshopJava 8 Workshop
Java 8 Workshop
 
New Features in JDK 8
New Features in JDK 8New Features in JDK 8
New Features in JDK 8
 
Lambdas and Laughs
Lambdas and LaughsLambdas and Laughs
Lambdas and Laughs
 
Intro to Reactive Thinking and RxJava 2
Intro to Reactive Thinking and RxJava 2Intro to Reactive Thinking and RxJava 2
Intro to Reactive Thinking and RxJava 2
 
Lecture 2 part 3
Lecture 2 part 3Lecture 2 part 3
Lecture 2 part 3
 
Java 8
Java 8Java 8
Java 8
 
New features in jdk8 iti
New features in jdk8 itiNew features in jdk8 iti
New features in jdk8 iti
 
Introduction to Map-Reduce Programming with Hadoop
Introduction to Map-Reduce Programming with HadoopIntroduction to Map-Reduce Programming with Hadoop
Introduction to Map-Reduce Programming with Hadoop
 
Java 8 by example!
Java 8 by example!Java 8 by example!
Java 8 by example!
 
Refactoring to Macros with Clojure
Refactoring to Macros with ClojureRefactoring to Macros with Clojure
Refactoring to Macros with Clojure
 
Stata Programming Cheat Sheet
Stata Programming Cheat SheetStata Programming Cheat Sheet
Stata Programming Cheat Sheet
 
Stata cheatsheet programming
Stata cheatsheet programmingStata cheatsheet programming
Stata cheatsheet programming
 
Python - Lecture 12
Python - Lecture 12Python - Lecture 12
Python - Lecture 12
 
Java 8 stream and c# 3.5
Java 8 stream and c# 3.5Java 8 stream and c# 3.5
Java 8 stream and c# 3.5
 
Matlab Functions
Matlab FunctionsMatlab Functions
Matlab Functions
 
Java 8 Intro - Core Features
Java 8 Intro - Core FeaturesJava 8 Intro - Core Features
Java 8 Intro - Core Features
 
Hadoop - Introduction to mapreduce
Hadoop -  Introduction to mapreduceHadoop -  Introduction to mapreduce
Hadoop - Introduction to mapreduce
 
Hadoop ecosystem
Hadoop ecosystemHadoop ecosystem
Hadoop ecosystem
 

More from José Paumard

Loom Virtual Threads in the JDK 19
Loom Virtual Threads in the JDK 19Loom Virtual Threads in the JDK 19
Loom Virtual Threads in the JDK 19
José Paumard
 
The Future of Java: Records, Sealed Classes and Pattern Matching
The Future of Java: Records, Sealed Classes and Pattern MatchingThe Future of Java: Records, Sealed Classes and Pattern Matching
The Future of Java: Records, Sealed Classes and Pattern Matching
José Paumard
 
Designing functional and fluent API: application to some GoF patterns
Designing functional and fluent API: application to some GoF patternsDesigning functional and fluent API: application to some GoF patterns
Designing functional and fluent API: application to some GoF patterns
José Paumard
 
The Sincerest Form of Flattery
The Sincerest Form of FlatteryThe Sincerest Form of Flattery
The Sincerest Form of Flattery
José Paumard
 
The Sincerest Form of Flattery
The Sincerest Form of FlatteryThe Sincerest Form of Flattery
The Sincerest Form of Flattery
José Paumard
 
Designing functional and fluent API: example of the Visitor Pattern
Designing functional and fluent API: example of the Visitor PatternDesigning functional and fluent API: example of the Visitor Pattern
Designing functional and fluent API: example of the Visitor Pattern
José Paumard
 
Construire son JDK en 10 étapes
Construire son JDK en 10 étapesConstruire son JDK en 10 étapes
Construire son JDK en 10 étapes
José Paumard
 
Java Keeps Throttling Up!
Java Keeps Throttling Up!Java Keeps Throttling Up!
Java Keeps Throttling Up!
José Paumard
 
Asynchronous Systems with Fn Flow
Asynchronous Systems with Fn FlowAsynchronous Systems with Fn Flow
Asynchronous Systems with Fn Flow
José Paumard
 
Java Full Throttle
Java Full ThrottleJava Full Throttle
Java Full Throttle
José Paumard
 
JAX-RS and CDI Bike the (Reactive) Bridge
JAX-RS and CDI Bike the (Reactive) BridgeJAX-RS and CDI Bike the (Reactive) Bridge
JAX-RS and CDI Bike the (Reactive) Bridge
José Paumard
 
Streams in the wild
Streams in the wildStreams in the wild
Streams in the wild
José Paumard
 
JAX RS and CDI bike the reactive bridge
JAX RS and CDI bike the reactive bridgeJAX RS and CDI bike the reactive bridge
JAX RS and CDI bike the reactive bridge
José Paumard
 
Free your lambdas
Free your lambdasFree your lambdas
Free your lambdas
José Paumard
 
Linked to ArrayList: the full story
Linked to ArrayList: the full storyLinked to ArrayList: the full story
Linked to ArrayList: the full story
José Paumard
 
Free your lambdas
Free your lambdasFree your lambdas
Free your lambdas
José Paumard
 
ArrayList et LinkedList sont dans un bateau
ArrayList et LinkedList sont dans un bateauArrayList et LinkedList sont dans un bateau
ArrayList et LinkedList sont dans un bateau
José Paumard
 
Java SE 8 for Java EE developers
Java SE 8 for Java EE developersJava SE 8 for Java EE developers
Java SE 8 for Java EE developers
José Paumard
 
Asynchronous API in Java8, how to use CompletableFuture
Asynchronous API in Java8, how to use CompletableFutureAsynchronous API in Java8, how to use CompletableFuture
Asynchronous API in Java8, how to use CompletableFuture
José Paumard
 
Java 8 Streams and Rx Java Comparison
Java 8 Streams and Rx Java ComparisonJava 8 Streams and Rx Java Comparison
Java 8 Streams and Rx Java Comparison
José Paumard
 

More from José Paumard (20)

Loom Virtual Threads in the JDK 19
Loom Virtual Threads in the JDK 19Loom Virtual Threads in the JDK 19
Loom Virtual Threads in the JDK 19
 
The Future of Java: Records, Sealed Classes and Pattern Matching
The Future of Java: Records, Sealed Classes and Pattern MatchingThe Future of Java: Records, Sealed Classes and Pattern Matching
The Future of Java: Records, Sealed Classes and Pattern Matching
 
Designing functional and fluent API: application to some GoF patterns
Designing functional and fluent API: application to some GoF patternsDesigning functional and fluent API: application to some GoF patterns
Designing functional and fluent API: application to some GoF patterns
 
The Sincerest Form of Flattery
The Sincerest Form of FlatteryThe Sincerest Form of Flattery
The Sincerest Form of Flattery
 
The Sincerest Form of Flattery
The Sincerest Form of FlatteryThe Sincerest Form of Flattery
The Sincerest Form of Flattery
 
Designing functional and fluent API: example of the Visitor Pattern
Designing functional and fluent API: example of the Visitor PatternDesigning functional and fluent API: example of the Visitor Pattern
Designing functional and fluent API: example of the Visitor Pattern
 
Construire son JDK en 10 étapes
Construire son JDK en 10 étapesConstruire son JDK en 10 étapes
Construire son JDK en 10 étapes
 
Java Keeps Throttling Up!
Java Keeps Throttling Up!Java Keeps Throttling Up!
Java Keeps Throttling Up!
 
Asynchronous Systems with Fn Flow
Asynchronous Systems with Fn FlowAsynchronous Systems with Fn Flow
Asynchronous Systems with Fn Flow
 
Java Full Throttle
Java Full ThrottleJava Full Throttle
Java Full Throttle
 
JAX-RS and CDI Bike the (Reactive) Bridge
JAX-RS and CDI Bike the (Reactive) BridgeJAX-RS and CDI Bike the (Reactive) Bridge
JAX-RS and CDI Bike the (Reactive) Bridge
 
Streams in the wild
Streams in the wildStreams in the wild
Streams in the wild
 
JAX RS and CDI bike the reactive bridge
JAX RS and CDI bike the reactive bridgeJAX RS and CDI bike the reactive bridge
JAX RS and CDI bike the reactive bridge
 
Free your lambdas
Free your lambdasFree your lambdas
Free your lambdas
 
Linked to ArrayList: the full story
Linked to ArrayList: the full storyLinked to ArrayList: the full story
Linked to ArrayList: the full story
 
Free your lambdas
Free your lambdasFree your lambdas
Free your lambdas
 
ArrayList et LinkedList sont dans un bateau
ArrayList et LinkedList sont dans un bateauArrayList et LinkedList sont dans un bateau
ArrayList et LinkedList sont dans un bateau
 
Java SE 8 for Java EE developers
Java SE 8 for Java EE developersJava SE 8 for Java EE developers
Java SE 8 for Java EE developers
 
Asynchronous API in Java8, how to use CompletableFuture
Asynchronous API in Java8, how to use CompletableFutureAsynchronous API in Java8, how to use CompletableFuture
Asynchronous API in Java8, how to use CompletableFuture
 
Java 8 Streams and Rx Java Comparison
Java 8 Streams and Rx Java ComparisonJava 8 Streams and Rx Java Comparison
Java 8 Streams and Rx Java Comparison
 

Recently uploaded

Unit 8 - Information and Communication Technology (Paper I).pdf
Unit 8 - Information and Communication Technology (Paper I).pdfUnit 8 - Information and Communication Technology (Paper I).pdf
Unit 8 - Information and Communication Technology (Paper I).pdf
Thiyagu K
 
Adversarial Attention Modeling for Multi-dimensional Emotion Regression.pdf
Adversarial Attention Modeling for Multi-dimensional Emotion Regression.pdfAdversarial Attention Modeling for Multi-dimensional Emotion Regression.pdf
Adversarial Attention Modeling for Multi-dimensional Emotion Regression.pdf
Po-Chuan Chen
 
Instructions for Submissions thorugh G- Classroom.pptx
Instructions for Submissions thorugh G- Classroom.pptxInstructions for Submissions thorugh G- Classroom.pptx
Instructions for Submissions thorugh G- Classroom.pptx
Jheel Barad
 
Operation Blue Star - Saka Neela Tara
Operation Blue Star   -  Saka Neela TaraOperation Blue Star   -  Saka Neela Tara
Operation Blue Star - Saka Neela Tara
Balvir Singh
 
Acetabularia Information For Class 9 .docx
Acetabularia Information For Class 9  .docxAcetabularia Information For Class 9  .docx
Acetabularia Information For Class 9 .docx
vaibhavrinwa19
 
678020731-Sumas-y-Restas-Para-Colorear.pdf
678020731-Sumas-y-Restas-Para-Colorear.pdf678020731-Sumas-y-Restas-Para-Colorear.pdf
678020731-Sumas-y-Restas-Para-Colorear.pdf
CarlosHernanMontoyab2
 
Lapbook sobre os Regimes Totalitários.pdf
Lapbook sobre os Regimes Totalitários.pdfLapbook sobre os Regimes Totalitários.pdf
Lapbook sobre os Regimes Totalitários.pdf
Jean Carlos Nunes Paixão
 
Introduction to AI for Nonprofits with Tapp Network
Introduction to AI for Nonprofits with Tapp NetworkIntroduction to AI for Nonprofits with Tapp Network
Introduction to AI for Nonprofits with Tapp Network
TechSoup
 
A Strategic Approach: GenAI in Education
A Strategic Approach: GenAI in EducationA Strategic Approach: GenAI in Education
A Strategic Approach: GenAI in Education
Peter Windle
 
Model Attribute Check Company Auto Property
Model Attribute  Check Company Auto PropertyModel Attribute  Check Company Auto Property
Model Attribute Check Company Auto Property
Celine George
 
Mule 4.6 & Java 17 Upgrade | MuleSoft Mysore Meetup #46
Mule 4.6 & Java 17 Upgrade | MuleSoft Mysore Meetup #46Mule 4.6 & Java 17 Upgrade | MuleSoft Mysore Meetup #46
Mule 4.6 & Java 17 Upgrade | MuleSoft Mysore Meetup #46
MysoreMuleSoftMeetup
 
Home assignment II on Spectroscopy 2024 Answers.pdf
Home assignment II on Spectroscopy 2024 Answers.pdfHome assignment II on Spectroscopy 2024 Answers.pdf
Home assignment II on Spectroscopy 2024 Answers.pdf
Tamralipta Mahavidyalaya
 
TESDA TM1 REVIEWER FOR NATIONAL ASSESSMENT WRITTEN AND ORAL QUESTIONS WITH A...
TESDA TM1 REVIEWER  FOR NATIONAL ASSESSMENT WRITTEN AND ORAL QUESTIONS WITH A...TESDA TM1 REVIEWER  FOR NATIONAL ASSESSMENT WRITTEN AND ORAL QUESTIONS WITH A...
TESDA TM1 REVIEWER FOR NATIONAL ASSESSMENT WRITTEN AND ORAL QUESTIONS WITH A...
EugeneSaldivar
 
Guidance_and_Counselling.pdf B.Ed. 4th Semester
Guidance_and_Counselling.pdf B.Ed. 4th SemesterGuidance_and_Counselling.pdf B.Ed. 4th Semester
Guidance_and_Counselling.pdf B.Ed. 4th Semester
Atul Kumar Singh
 
The Accursed House by Émile Gaboriau.pptx
The Accursed House by Émile Gaboriau.pptxThe Accursed House by Émile Gaboriau.pptx
The Accursed House by Émile Gaboriau.pptx
DhatriParmar
 
Digital Tools and AI for Teaching Learning and Research
Digital Tools and AI for Teaching Learning and ResearchDigital Tools and AI for Teaching Learning and Research
Digital Tools and AI for Teaching Learning and Research
Vikramjit Singh
 
CLASS 11 CBSE B.St Project AIDS TO TRADE - INSURANCE
CLASS 11 CBSE B.St Project AIDS TO TRADE - INSURANCECLASS 11 CBSE B.St Project AIDS TO TRADE - INSURANCE
CLASS 11 CBSE B.St Project AIDS TO TRADE - INSURANCE
BhavyaRajput3
 
The Roman Empire A Historical Colossus.pdf
The Roman Empire A Historical Colossus.pdfThe Roman Empire A Historical Colossus.pdf
The Roman Empire A Historical Colossus.pdf
kaushalkr1407
 
Welcome to TechSoup New Member Orientation and Q&A (May 2024).pdf
Welcome to TechSoup   New Member Orientation and Q&A (May 2024).pdfWelcome to TechSoup   New Member Orientation and Q&A (May 2024).pdf
Welcome to TechSoup New Member Orientation and Q&A (May 2024).pdf
TechSoup
 
Sha'Carri Richardson Presentation 202345
Sha'Carri Richardson Presentation 202345Sha'Carri Richardson Presentation 202345
Sha'Carri Richardson Presentation 202345
beazzy04
 

Recently uploaded (20)

Unit 8 - Information and Communication Technology (Paper I).pdf
Unit 8 - Information and Communication Technology (Paper I).pdfUnit 8 - Information and Communication Technology (Paper I).pdf
Unit 8 - Information and Communication Technology (Paper I).pdf
 
Adversarial Attention Modeling for Multi-dimensional Emotion Regression.pdf
Adversarial Attention Modeling for Multi-dimensional Emotion Regression.pdfAdversarial Attention Modeling for Multi-dimensional Emotion Regression.pdf
Adversarial Attention Modeling for Multi-dimensional Emotion Regression.pdf
 
Instructions for Submissions thorugh G- Classroom.pptx
Instructions for Submissions thorugh G- Classroom.pptxInstructions for Submissions thorugh G- Classroom.pptx
Instructions for Submissions thorugh G- Classroom.pptx
 
Operation Blue Star - Saka Neela Tara
Operation Blue Star   -  Saka Neela TaraOperation Blue Star   -  Saka Neela Tara
Operation Blue Star - Saka Neela Tara
 
Acetabularia Information For Class 9 .docx
Acetabularia Information For Class 9  .docxAcetabularia Information For Class 9  .docx
Acetabularia Information For Class 9 .docx
 
678020731-Sumas-y-Restas-Para-Colorear.pdf
678020731-Sumas-y-Restas-Para-Colorear.pdf678020731-Sumas-y-Restas-Para-Colorear.pdf
678020731-Sumas-y-Restas-Para-Colorear.pdf
 
Lapbook sobre os Regimes Totalitários.pdf
Lapbook sobre os Regimes Totalitários.pdfLapbook sobre os Regimes Totalitários.pdf
Lapbook sobre os Regimes Totalitários.pdf
 
Introduction to AI for Nonprofits with Tapp Network
Introduction to AI for Nonprofits with Tapp NetworkIntroduction to AI for Nonprofits with Tapp Network
Introduction to AI for Nonprofits with Tapp Network
 
A Strategic Approach: GenAI in Education
A Strategic Approach: GenAI in EducationA Strategic Approach: GenAI in Education
A Strategic Approach: GenAI in Education
 
Model Attribute Check Company Auto Property
Model Attribute  Check Company Auto PropertyModel Attribute  Check Company Auto Property
Model Attribute Check Company Auto Property
 
Mule 4.6 & Java 17 Upgrade | MuleSoft Mysore Meetup #46
Mule 4.6 & Java 17 Upgrade | MuleSoft Mysore Meetup #46Mule 4.6 & Java 17 Upgrade | MuleSoft Mysore Meetup #46
Mule 4.6 & Java 17 Upgrade | MuleSoft Mysore Meetup #46
 
Home assignment II on Spectroscopy 2024 Answers.pdf
Home assignment II on Spectroscopy 2024 Answers.pdfHome assignment II on Spectroscopy 2024 Answers.pdf
Home assignment II on Spectroscopy 2024 Answers.pdf
 
TESDA TM1 REVIEWER FOR NATIONAL ASSESSMENT WRITTEN AND ORAL QUESTIONS WITH A...
TESDA TM1 REVIEWER  FOR NATIONAL ASSESSMENT WRITTEN AND ORAL QUESTIONS WITH A...TESDA TM1 REVIEWER  FOR NATIONAL ASSESSMENT WRITTEN AND ORAL QUESTIONS WITH A...
TESDA TM1 REVIEWER FOR NATIONAL ASSESSMENT WRITTEN AND ORAL QUESTIONS WITH A...
 
Guidance_and_Counselling.pdf B.Ed. 4th Semester
Guidance_and_Counselling.pdf B.Ed. 4th SemesterGuidance_and_Counselling.pdf B.Ed. 4th Semester
Guidance_and_Counselling.pdf B.Ed. 4th Semester
 
The Accursed House by Émile Gaboriau.pptx
The Accursed House by Émile Gaboriau.pptxThe Accursed House by Émile Gaboriau.pptx
The Accursed House by Émile Gaboriau.pptx
 
Digital Tools and AI for Teaching Learning and Research
Digital Tools and AI for Teaching Learning and ResearchDigital Tools and AI for Teaching Learning and Research
Digital Tools and AI for Teaching Learning and Research
 
CLASS 11 CBSE B.St Project AIDS TO TRADE - INSURANCE
CLASS 11 CBSE B.St Project AIDS TO TRADE - INSURANCECLASS 11 CBSE B.St Project AIDS TO TRADE - INSURANCE
CLASS 11 CBSE B.St Project AIDS TO TRADE - INSURANCE
 
The Roman Empire A Historical Colossus.pdf
The Roman Empire A Historical Colossus.pdfThe Roman Empire A Historical Colossus.pdf
The Roman Empire A Historical Colossus.pdf
 
Welcome to TechSoup New Member Orientation and Q&A (May 2024).pdf
Welcome to TechSoup   New Member Orientation and Q&A (May 2024).pdfWelcome to TechSoup   New Member Orientation and Q&A (May 2024).pdf
Welcome to TechSoup New Member Orientation and Q&A (May 2024).pdf
 
Sha'Carri Richardson Presentation 202345
Sha'Carri Richardson Presentation 202345Sha'Carri Richardson Presentation 202345
Sha'Carri Richardson Presentation 202345
 

Lambdas and Streams Master Class Part 2

  • 1. #Devoxx Java Lambda Stream Master Class – Part 2 @StuartMarks @JosePaumard
  • 2. #LambdaHOL#Devoxx Stuart Marks JDK Core Libraries Developer Java Plaform Group, Oracle Twitter: @stuartmarks
  • 5. #LambdaHOL#Devoxx Lambda/Streams Master Class 2 Setup Map, Filter, FlatMap Reduction, Function combination Collectors.toMap() Collectors.groupingBy() Cascading Collectors Streaming a Map Streaming over Indexes
  • 6. #LambdaHOL#Devoxx Back to the Comparator How to deal with null names? Comparator<Person> cmp = Comparator.comparing(Person::getLastName) .thenComparing(Person::getFirstName) .thenComparing(Person::getAge);
  • 7. #LambdaHOL#Devoxx Back to the Comparator In fact, this comparator: Is equivalent to this one: Comparator.comparing(Person::getLastName) Comparator.comparing(Person::getLastName, Comparator.naturalOrder())
  • 8. #LambdaHOL#Devoxx Back to the Comparator This allows this pattern: So, to deal with null values: Comparator.comparing(Person::getLastName, Comparator.nullsLast(Comparator.naturalOrder())) Comparator.comparing(Person::getLastName, Comparator.comparing(String::length))
  • 9. #LambdaHOL#Devoxx Back to the Comparator If we need to deal with null Person objects and null names: Comparator.nullsLast( Comparator.comparing(Person::getLastName, Comparator.nullsLast(Comparator.naturalOrder()) ) )
  • 11. #LambdaHOL#Devoxx The LambdaHOL You can find it here https://github.com/stuart-marks/LambdaHOLv2 https://github.com/JosePaumard/lambda-master-class-part2 https://github.com/JosePaumard/lambda-master-class-part1
  • 12. #LambdaHOL#Devoxx Input Data — Alphabet List<String> alphabet = List.of( "alfa", "bravo", "charlie", "delta", "echo", "foxtrot", "golf", "hotel", "india", "juliet", "kilo", "lima", "mike", "november", "oscar", "papa", "quebec", "romeo", "sierra", "tango", "uniform", "victor", "whiskey", "x-ray", "yankee", "zulu");
  • 13. #LambdaHOL#Devoxx Input Data — Sonnet List<String> sonnet = List.of( "From fairest creatures we desire increase,", "That thereby beauty's rose might never die,", "But as the riper should by time decease,", "His tender heir might bear his memory:", "But thou contracted to thine own bright eyes,", "Feed'st thy light's flame with self-substantial fuel,", "Making a famine where abundance lies,", "Thy self thy foe, to thy sweet self too cruel:", "Thou that art now the world's fresh ornament,", "And only herald to the gaudy spring,", "Within thine own bud buriest thy content,", "And, tender churl, mak'st waste in niggarding:", "Pity the world, or else this glutton be,", "To eat the world's due, by the grave and thee.");
  • 14. #LambdaHOL#Devoxx Helper Method — expand() expand("abc") ⇒ ["a", "b", "c"] List<String> expand(String s) { return s.codePoints() .mapToObj(Character::toString) .collect(toList()); }
  • 16. #LambdaHOL#Devoxx Map, Filter Example • From the Alphabet list • Map to upper case • Only keep the words with 6 letters
  • 17. #LambdaHOL#Devoxx Map, Filter Example alphabet.stream() .map(String::toUpperCase) .filter(word -> word.length() == 6) .forEach(System.out::println); JULIET QUEBEC SIERRA VICTOR YANKEE
  • 19. #LambdaHOL#Devoxx FlatMap • Intermediate stream operation • Consumes one element • May produce zero or more elements • Compare to map: consumes one, produces one • How is zero-or-more represented? A stream! • T ⇒ Stream<R>
  • 20. #LambdaHOL#Devoxx FlatMap Given a list of strings... [alfa, bravo, charlie, ...] expand each string to a list of one-letter strings [ [a, l, f, a], [b, r, a, v, o], [c, h, ...] ... ] but «flatten» the nesting structure [a, l, f, a, b, r, a, v, o, c, h, ...]
  • 21. #LambdaHOL#Devoxx FlatMap [[a, l, f, a], [b, r, a, v, o], [c, h, ...] ...] List<List<String>> flatMap1() { return alphabet.stream() .map(word -> expand(word)) .collect(toList()); }
  • 22. #LambdaHOL#Devoxx FlatMap [a, l, f, a, b, r, a, v, o, c, h, a, r, l, i, e, d, e, l, ...] List<String> flatMap2() { return alphabet.stream() .flatMap(word -> expand(word).stream()) .collect(toList()); }
  • 23. #LambdaHOL#Devoxx FlatMap — Exercise Split each line of the sonnet into words, and then collect all the words into a single list. To split a line into words, use line.split(" +") note: this returns an array, not a list or stream
  • 24. #LambdaHOL#Devoxx FlatMap — Solution Split each line of the sonnet into words, and then collect all the words into a single list. [From, fairest, creatures, we, desire, increase, ...] total 106 words List<String> flatMapSolution() { return sonnet.stream() .flatMap(line -> Arrays.stream(line.split(" +"))) .collect(toList()); }
  • 26. #LambdaHOL#Devoxx Computing Factorials Compute the factorial as a BigInteger using streams and reduction long number = 21; // result is 51_090_942_171_709_440_000
  • 27. #LambdaHOL#Devoxx Computing Factorials Compute the factorial as a BigInteger using streams and reduction long number = 21; BigInteger result = LongStream.rangeClosed(1, 21) .mapToObj(BigInteger::valueOf) .reduce(BigInteger.ONE, BigInteger::multiply); // result is 51_090_942_171_709_440_000
  • 29. #LambdaHOL#Devoxx Function Combination Suppose you have a shopping website where the customer can apply a filter to limit the products shown. List<Product> show(Predicate<Product> predicate) { return getAllProducts().stream() .filter(predicate) .collect(toList()); }
  • 30. #LambdaHOL#Devoxx Function Combination Suppose you want the customer to be able to apply two filters to the product list. Now, how about three filters? List<Product> show(Predicate<Product> p1, Predicate<Product> p2) { return getAllProducts().stream() .filter(p1.and(p2)) .collect(toList()); }
  • 31. #LambdaHOL#Devoxx Function Combination Two predicates can be combined using the Predicate.and() method. This is all we need to write a method that combines an arbitrary number of predicates. Predicate<Product> p1 = ... ; Predicate<Product> p2 = ... ; Predicate<Product> combined = p1.and(p2);
  • 32. #LambdaHOL#Devoxx Function Combination Reduction of a list over an operator applies that operator between each element. Predicate<Product> combine(List<Predicate<Product>> predicates) { Predicate<Product> temp = product -> true; for (Predicate<Product> cur : predicates) { temp = temp.and(cur); } return temp; }
  • 33. #LambdaHOL#Devoxx Function Combination Reduction of a list over an operator applies that operator between each element. Predicate<Product> combine(List<Predicate<Product>> predicates) { return predicates.stream() .reduce(product -> true, Predicate::and); }
  • 34. #LambdaHOL#Devoxx Function Combination Now apply this to the original problem: List<Product> show(List<Predicate<Product>> predicates) { Predicate<Product> combinedPredicate = combine(predicates); return getAllProducts().stream() .filter(combinedPredicate) .collect(toList()); }
  • 35. #LambdaHOL#Devoxx Function Combination — Exercise An IntUnaryOperator is a functional interface that takes an int and returns an int. Write a method that combines an arbitrary sized list of IntUnaryOperators into a single one. Use streams and the IntUnaryOperator.andThen() method. Use your method to combine functions that add one, multiply by two, and three.
  • 36. #LambdaHOL#Devoxx Function Combination — Exercise IntUnaryOperator combine(List<IntUnaryOperator> operators) { // TODO } IntUnaryOperator operator = combine(List.of(i -> i + 1, i -> i * 2, i -> i + 3)); System.out.println(operator.applyAsInt(5)); 15
  • 37. #LambdaHOL#Devoxx Function Combination — Solution IntUnaryOperator combine(List<IntUnaryOperator> operators) { return operators.stream() .reduce(i -> i, IntUnaryOperator::andThen); } IntUnaryOperator operator = combine(List.of(i -> i + 1, i -> i * 2, i -> i + 3)); System.out.println(operator.applyAsInt(5)); 15
  • 39. #LambdaHOL#Devoxx Collectors.toMap() Collectors.toMap(keyFunction, valueFunction) Takes each stream element ▪ runs the keyFunction to get a key ▪ runs the valueFunction to get a value ▪ enters computed (key, value) entries into the result map Returns the map as the final result
  • 40. #LambdaHOL#Devoxx Collectors.toMap() Given the alphabet words, create a map whose keys are the first letter and whose values are the words. Map<String, String> toMap1() { return alphabet.stream() .collect(toMap(word -> word.substring(0, 1), word -> word)); }
  • 41. #LambdaHOL#Devoxx Collectors.toMap() a => alfa b => bravo c => charlie d => delta e => echo f => foxtrot g => golf h => hotel i => india j => juliet k => kilo l => lima m => mike n => november o => oscar
  • 42. #LambdaHOL#Devoxx Collectors.toMap() Now create the first-letter map using the sonnet instead of the alphabet words. Map<String, String> toMap1() { return sonnet.stream() .collect(toMap(word -> word.substring(0, 1), word -> word)); }
  • 43. #LambdaHOL#Devoxx Collectors.toMap() Exception in thread "main" java.lang.IllegalStateException: Duplicate key B (attempted merging values But as the riper should by time decease, and But thou contracted to thine own bright eyes,) at java.base/java.util.stream.Collectors.duplicateKeyException(Collectors.java:133) at java.base/java.util.stream.Collectors.lambda$uniqKeysMapAccumulator$1(Collectors.java:180) at java.base/java.util.stream.ReduceOps$3ReducingSink.accept(ReduceOps.java:169) at java.base/java.util.AbstractList$RandomAccessSpliterator.forEachRemaining(AbstractList.java:720)
  • 44. #LambdaHOL#Devoxx Collectors.toMap() The simple (two-arg) toMap() requires that all keys be unique. Throws exception if duplicate keys are encountered. To handle this, a third arg mergeFunction can be provided. It takes the values of the duplicate keys and returns a merged value.
  • 45. #LambdaHOL#Devoxx Collectors.toMap() Use a merge function that simply returns its first argument. “First wins.” Map<String, String> toMap3() { return sonnet.stream() .collect(toMap(line -> line.substring(0, 1), line -> line, (line1, line2) -> line1 // merge )); }
  • 46. #LambdaHOL#Devoxx Collectors.toMap() Eight of fourteen lines remain, so some duplicates were lost. P => Pity the world, or else this glutton be, A => And only herald to the gaudy spring, B => But as the riper should by time decease, T => That thereby beauty's rose might never die, F => From fairest creatures we desire increase, W => Within thine own bud buriest thy content, H => His tender heir might bear his memory: M => Making a famine where abundance lies,
  • 47. #LambdaHOL#Devoxx Collectors.toMap() Use a “last wins” merge function. Map<String, String> toMap4() { return sonnet.stream() .collect(toMap(line -> line.substring(0, 1), line -> line, (line1, line2) -> line2 // merge )); }
  • 48. #LambdaHOL#Devoxx Collectors.toMap() Eight entries, but some are different. P => Pity the world, or else this glutton be, A => And, tender churl, mak'st waste in niggarding: B => But thou contracted to thine own bright eyes, T => To eat the world's due, by the grave and thee. F => Feed'st thy light's flame with self-substantial fuel, W => Within thine own bud buriest thy content, H => His tender heir might bear his memory: M => Making a famine where abundance lies,
  • 49. #LambdaHOL#Devoxx Collectors.toMap() — Exercise Create a map from the lines of the sonnet, with map keys being the first letter of the line, and values being the line. For duplicate keys, concatenate the lines with a newline in between.
  • 50. #LambdaHOL#Devoxx Collectors.toMap() — Solution Map<String, String> toMapSolution() { return sonnet.stream() .collect( toMap(line -> line.substring(0, 1), line -> line, (line1, line2) -> line1 + System.lineSeparator() + line2)); }
  • 51. #LambdaHOL#Devoxx Collectors.toMap() — Solution P => Pity the world, or else this glutton be, A => And only herald to the gaudy spring, And, tender churl, mak'st waste in niggarding: B => But as the riper should by time decease, But thou contracted to thine own bright eyes, T => That thereby beauty's rose might never die, Thy self thy foe, to thy sweet self too cruel: Thou that art now the world's fresh ornament, To eat the world's due, by the grave and thee. F => From fairest creatures we desire increase, Feed'st thy light's flame with self-substantial fuel, W => Within thine own bud buriest thy content, H => His tender heir might bear his memory: M => Making a famine where abundance lies,
  • 53. #LambdaHOL#Devoxx Collectors.groupingBy() The groupingBy() collector is a fancy way of collecting a map from a stream. In its simplest form, it takes a classifier function to transform each stream element into a key. Map values are a list of stream elements classified into the same key. Stream<T> ⇒ Map<K, List<V>>
  • 54. #LambdaHOL#Devoxx Collectors.groupingBy() From the alphabet words, create a map whose keys are the word length, and whose values are a list of those words. First start off with toMap(). Map<Integer, List<String>> groupingBy1() { return alphabet.stream() .collect( toMap( word -> word.length(), word -> new ArrayList<>(Arrays.asList(word)), (list1, list2) -> { list1.addAll(list2); return list1; })); }
  • 55. #LambdaHOL#Devoxx Collectors.groupingBy() 4 => [alfa, echo, golf, kilo, lima, mike, papa, zulu] 5 => [bravo, delta, hotel, india, oscar, romeo, tango, x-ray] 6 => [juliet, quebec, sierra, victor, yankee] 7 => [charlie, foxtrot, uniform, whiskey] 8 => [november]
  • 56. #LambdaHOL#Devoxx Collectors.groupingBy() Change toMap() to groupingBy(). Same result! Map<Integer, List<String>> groupingBy1() { return alphabet.stream() .collect(toMap(String::length, s -> new ArrayList<>(Arrays.asList(s)), (a, b) -> { a.addAll(b); return a; })); } Map<Integer, List<String>> groupingBy2() { return alphabet.stream() .collect(groupingBy(String::length)); }
  • 57. #LambdaHOL#Devoxx Collectors.groupingBy() — Exercise Collect the lines of the sonnet into a map, whose keys are the first letter of each line, and whose values are a list of lines beginning with that letter.
  • 58. #LambdaHOL#Devoxx Collectors.groupingBy() — Solution Map<String, List<String>> groupingBySolution() { return sonnet.stream() .collect(groupingBy(line -> line.substring(0, 1))); }
  • 59. #LambdaHOL#Devoxx Collectors.groupingBy() — Solution P => [Pity the world, or else this glutton be,] A => [And only herald to the gaudy spring,, And, tender churl, mak'st waste in niggarding:] B => [But as the riper should by time decease,, But thou contracted to thine own bright eyes,] T => [That thereby beauty's rose might never die,, Thy self thy foe, to thy sweet self too cruel:, Thou that art now the world's fresh ornament,, To eat the world's due, by the grave and thee.] F => [From fairest creatures we desire increase,, Feed'st thy light's flame with self-substantial fuel,] W => [Within thine own bud buriest thy content,] H => [His tender heir might bear his memory:] M => [Making a famine where abundance lies,]
  • 61. #LambdaHOL#Devoxx Cascading Collectors The groupingBy() collector seems restrictive: it collects stream elements into a list. This behavior can be modified by providing a “downstream” collector as another argument. groupingBy(classifier, downstream)
  • 62. #LambdaHOL#Devoxx Collectors.counting() A useful downstream collector is counting() The counting() collector is analogous to Stream.count().
  • 63. #LambdaHOL#Devoxx Collectors.counting() The pattern is the following: Map<String, Long> cascading2() { return sonnet.stream() .collect(groupingBy(line -> line.substring(0, 1), Collectors.counting())); }
  • 64. #LambdaHOL#Devoxx Collectors.counting() P => 1L A => 2L B => 2L T => 4L F => 2L W => 1L H => 1L M => 1L
  • 65. #LambdaHOL#Devoxx Collectors.mapping() Another useful downstream collector is mapping(): mapping(mapperFunction, downstream2) The mapping() collector is analogous to Stream.map(). It applies a mapper function to an element and passes the result downstream — to a second downstream collector.
  • 66. #LambdaHOL#Devoxx Collectors.mapping() These are equivalent: Map<String, List<String>> cascading2() { return sonnet.stream() .collect( groupingBy( line -> line.substring(0, 1), mapping(line -> line, toList()) )); } Map<String, List<String>> cascading1() { return sonnet.stream() .collect(groupingBy(line -> line.substring(0, 1))); }
  • 67. #LambdaHOL#Devoxx Collectors.mapping() The using mapping() as the downstream collector enables: ▪ the stream elements collected into map values can be transformed ▪ the transformed elements can be collected or reduced differently
  • 68. #LambdaHOL#Devoxx Collectors.mapping() Map<String, List<Integer>> cascading3() { return sonnet.stream() .collect( groupingBy( line -> line.substring(0, 1), mapping(String::length, toList()) )); } P => [40] A => [36, 46] B => [40, 45] T => [43, 46, 45, 46] F => [42, 53] W => [41] H => [38] M => [37]
  • 69. #LambdaHOL#Devoxx Cascading Collectors — Exercise Group the lines of the sonnet by first letter, and collect the first word of grouped lines into a set. To extract the first word of a line, use string.split(" +")[0]
  • 70. #LambdaHOL#Devoxx Cascading Collectors — Solution Map<String, Set<Integer>> cascading3() { return sonnet.stream() .collect( groupingBy( line -> line.substring(0, 1), mapping(line -> line.split(" +")[0], toSet()) )); } P => [Pity] A => [And, And,] B => [But] T => [That, Thy, To, Thou] F => [Feed'st, From] W => [Within] H => [His] M => [Making]
  • 71. #LambdaHOL#Devoxx Cascading Collectors A first set of collectors that need downstream collectors to work: - mapping() - filtering() - flatMapping() Analogous to intermediate stream operations
  • 72. #LambdaHOL#Devoxx Cascading Collectors A second set of collectors: ▪ joining() ▪ counting() ▪ groupingBy(), toMap(), toUnmodifiableMap() ▪ toList(), toSet(), toUnmodifiableList() (and set) ▪ reducing() Analogous to terminal stream operations
  • 73. #LambdaHOL#Devoxx Cascading Collectors Group lines of the sonnet by first letter, and collect the grouped lines into a single string separated by newlines. Map<String, String> cascading4() { return sonnet.stream() .collect(groupingBy(line -> line.substring(0, 1), joining("n") ) ); }
  • 74. #LambdaHOL#Devoxx Cascading Collectors P => Pity the world, or else this glutton be, A => And only herald to the gaudy spring, And, tender churl, mak'st waste in niggarding: B => But as the riper should by time decease, But thou contracted to thine own bright eyes, T => That thereby beauty's rose might never die, Thy self thy foe, to thy sweet self too cruel: Thou that art now the world's fresh ornament, To eat the world's due, by the grave and thee. F => From fairest creatures we desire increase, Feed'st thy light's flame with self-substantial fuel, W => Within thine own bud buriest thy content, H => His tender heir might bear his memory: M => Making a famine where abundance lies,
  • 75. #LambdaHOL#Devoxx Cascading Collectors — Exercise Generate a frequency table of letters in the sonnet. Remember the expand() helper method. Hints: use flatMap(), groupingBy(), and counting().
  • 76. #LambdaHOL#Devoxx Cascading Collectors — Solution Map<String, Long> cascadingSolution2() { return sonnet.stream() .flatMap(line -> expand(line).stream()) .collect(groupingBy(ch -> ch, counting())); } A => 2 B => 2 F => 2 H => 1 M => 1 P => 1 T => 4 W => 1 => 92 a => 28 b => 11 c => 9 d => 20 e => 68 f => 9 g => 12 ' => 6 h => 33 i => 29 k => 2 l => 18 , => 15 - => 1 m => 10 . => 1 n => 29 o => 25 p => 2 r => 33 s => 30 t => 54 u => 17 v => 2 w => 11 y => 14 : => 3
  • 78. #LambdaHOL#Devoxx Streaming a Map Find the most frequently occurring word from the Sonnet - 1st step: find one of those words - 2nd step: find all those words in a list
  • 79. #LambdaHOL#Devoxx Streaming a Map Two hints: 1) You cannot stream a map. To stream a map, you need to get a stream of entries from its entrySet(). Stream<Map.Entry<K, V>> stream = map.entrySet().stream();
  • 80. #LambdaHOL#Devoxx Streaming a Map Two hints: 2) There is a Stream.max() method And Map.Entry provides comparators stream.max(comparator) .orElseThrow(); // max returns an Optional stream.max(Map.Entry.comparingByValue()) .orElseThrow(); // max returns an Optional
  • 81. #LambdaHOL#Devoxx Inverting a Map Suppose there are multiple maximum values Max finds one of them Finding all of them can be done by converting a Map<word, count> to a Map<count, List<word>>
  • 83. #LambdaHOL#Devoxx Streaming Over Indexes Sometimes you need to process groups of adjacent elements or a “sliding window” of elements from a stream. The usual way of streaming elements doesn’t handle this well. If you have the elements in an array or random- access list, you can work around this limitation by streaming indexes instead of elements.
  • 84. #LambdaHOL#Devoxx Streaming Over Indexes Split into sublists of size N adjacent elements: N=3: List<List<String>> streamIndexes1(int N) { int SIZE = alphabet.size(); return IntStream.range(0, SIZE/N) .mapToObj(i -> alphabet.subList(N*i, N*(i+1))) .collect(toList()); } [[alfa, bravo, charlie], [delta, echo, foxtrot], [golf, hotel, india], [juliet, kilo, lima], [mike, november, oscar], [papa, quebec, romeo], [sierra, tango, uniform], [victor, whiskey, x-ray]]
  • 85. #LambdaHOL#Devoxx Streaming Over Indexes Adjust ranges and protect bounds with min(): List<List<String>> streamIndexes2(int N) { int SIZE = alphabet.size(); return IntStream.range(0, (SIZE+N-1)/N) .mapToObj(i -> alphabet.subList(N*i, Math.min(SIZE, N*(i+1)))) .collect(toList()); } [[alfa, bravo, charlie], [delta, echo, foxtrot], [golf, hotel, india], [juliet, kilo, lima], [mike, november, oscar], [papa, quebec, romeo], [sierra, tango, uniform], [victor, whiskey, x-ray], [yankee, zulu]]
  • 86. #LambdaHOL#Devoxx Streaming Over Indexes Alternatively, use rangeClosed(): List<List<String>> streamIndexes2(int N) { int SIZE = alphabet.size(); return IntStream.rangeClosed(0, (SIZE+N-1)/N) .mapToObj(i -> alphabet.subList(N*i, Math.min(SIZE, N*(i+1)))) .collect(toList()); } [[alfa, bravo, charlie], [delta, echo, foxtrot], [golf, hotel, india], [juliet, kilo, lima], [mike, november, oscar], [papa, quebec, romeo], [sierra, tango, uniform], [victor, whiskey, x-ray], [yankee, zulu]]
  • 87. #LambdaHOL#Devoxx Streaming Over Indexes — Exercise From the alphabet list, produce a list of overlapping sublists of length N (sliding window) [[alfa, bravo, charlie], [bravo, charlie, delta], [charlie, delta, echo], [delta, echo, foxtrot], [echo, foxtrot, golf], ...
  • 88. #LambdaHOL#Devoxx Streaming Over Indexes — Solution One solution: [[alfa, bravo, charlie], [bravo, charlie, delta], [charlie, delta, echo], [delta, echo, foxtrot], [echo, foxtrot, golf], ... List<List<String>> streamIndexesSolution1(int N) { int SIZE = alphabet.size(); return IntStream.range(0, SIZE-N+1) .mapToObj(i -> alphabet.subList(i, i+N)) .collect(toList()); }
  • 89. #LambdaHOL#Devoxx Streaming Over Indexes — Solution Variation: [[alfa, bravo, charlie], [bravo, charlie, delta], [charlie, delta, echo], [delta, echo, foxtrot], [echo, foxtrot, golf], ... List<List<String>> streamIndexesSolution2(int N) { int SIZE = alphabet.size(); return IntStream.rangeClosed(N, SIZE) .mapToObj(i -> alphabet.subList(i-N, i)) .collect(toList()); }
  • 90. #LambdaHOL#Devoxx Streaming Over Indexes — Exercise 2 Split the alphabet list into runs (sublists) of strings of non-decreasing length, preserving order. That is, within each sublist, the next string should always be the same length or longer. [[alfa, bravo, charlie], [delta], [echo, foxtrot], [golf, ...] ...]
  • 91. #LambdaHOL#Devoxx Streaming Over Indexes — Solution 2 Insight: a new sublist starts when this string is shorter than the previous string. Find the indexes where this occurs. [3, 4, 6, 10, 14, 15, 17, 19, 21, 23, 25] List<Integer> breaks = IntStream.range(1, alphabet.size()) .filter(i -> alphabet.get(i).length() < alphabet.get(i-1).length()) .boxed() .collect(toList());
  • 92. #LambdaHOL#Devoxx Streaming Over Indexes — Solution 2 We want sublists between these breaks. Run a stream over the breaks to generate sublists. [[delta], [echo, foxtrot], [golf, hotel, india, juliet], [kilo, lima, mike, november], [oscar], [papa, quebec], [romeo, sierra], [tango, uniform], [victor, whiskey], [x-ray, yankee]] List<List<String>> sublists = IntStream.range(0, breaks.size()-1) .mapToObj(i -> alphabet.subList(breaks.get(i), breaks.get(i+1))) .collect(toList());
  • 93. #LambdaHOL#Devoxx Streaming Over Indexes — Solution 2 Add starting and ending indexes to break list to pick up leading and trailing sublists. [[alfa, bravo, charlie], [delta], [echo, foxtrot], [golf, hotel, india, juliet], [kilo, lima, mike, november], [oscar], [papa, quebec], [romeo, sierra], [tango, uniform], [victor, whiskey], [x-ray, yankee], [zulu]] breaks.add(0, 0); breaks.add(alphabet.size()); List<List<String>> sublists = IntStream.range(0, breaks.size()-1) .mapToObj(i -> alphabet.subList(breaks.get(i), breaks.get(i+1))) .collect(toList());
  • 94. #LambdaHOL#Devoxx Streaming Over Indexes — Solution 2 List<Integer> breaks = IntStream.range(1, alphabet.size()) .filter(i -> alphabet.get(i).length() < alphabet.get(i-1).length()) .boxed() .collect(toList()); breaks.add(0, 0); breaks.add(alphabet.size()); List<List<String>> sublists = IntStream.range(0, breaks.size()-1) .mapToObj(i -> alphabet.subList(breaks.get(i), breaks.get(i+1))) .collect(toList());
  • 95. #LambdaHOL#Devoxx Streaming Over Indexes — Solution 2 [[alfa, bravo, charlie], [delta], [echo, foxtrot], [golf, hotel, india, juliet], [kilo, lima, mike, november], [oscar], [papa, quebec], [romeo, sierra], [tango, uniform], [victor, whiskey], [x-ray, yankee], [zulu]]