SlideShare una empresa de Scribd logo
1 de 189
Descargar para leer sin conexión
Journey’s End, JDK.IO, September 2016
Journey’s End
Collection and Reduction in the Stream API
JavaOne 2016
Maurice Naftalin
@mauricenaftalin
Journey’s End, JavaOne, September 2016
Maurice Naftalin
Journey’s End, JavaOne, September 2016
Maurice Naftalin
Java 5
Journey’s End, JavaOne, September 2016
Maurice Naftalin
Java 5 Java 8
Journey’s End, JavaOne, September 2016
Maurice Naftalin
Java 5 Java 8
Journey’s End, JavaOne, September 2016
Maurice Naftalin
Java 5 Java 8
2013
Journey’s End, JavaOne, September 2016
Maurice Naftalin
Java 5 Java 8
2014
Journey’s End, JavaOne, September 2016
Maurice Naftalin
Java 5 Java 8
2015
Journey’s End, JavaOne, September 2016
• Why collectors?
• Using the predefined collectors
• Worked problems
• Writing your own
Journey’s End – Agenda
Journey’s End, JavaOne, September 2016
Example Domain
city: City
name: String
age: int
Person
Person amy = new Person(Athens, "Amy", 21);

...
List<Person> people = Arrays.asList(jon, amy, bill);

Journey’s End, JavaOne, September 2016
Collectors: Journey’s End for a Stream
The Life of a Stream Element
• Born (at a spliterator)
• Transformed (by intermediate operations)
• Collected (by a terminal operation)
Journey’s End, JavaOne, September 2016
Collectors: Journey’s End for a Stream
The Life of a Stream Element
• Born (at a spliterator)
• Transformed (by intermediate operations)
• Collected (by a terminal operation)
Journey’s End, JavaOne, September 2016
Collectors: Journey’s End for a Stream
The Life of a Stream Element
• Born (at a spliterator)
• Transformed (by intermediate operations)
• Collected (by a terminal operation)
Journey’s End, JavaOne, September 2016
Collectors: Journey’s End for a Stream
?
The Life of a Stream Element
• Born (at a spliterator)
• Transformed (by intermediate operations)
• Collected (by a terminal operation)
Journey’s End, JavaOne, September 2016
Terminal Operations
– Search operations
– Side-effecting operations
– Reductions

Journey’s End, JavaOne, September 2016
Search Operations
Search operations -
• allMatch, anyMatch
• findAny, findFirst
boolean allAdults =
people.stream()

.allMatch(p -> p.getAge() >= 21);

Journey’s End, JavaOne, September 2016
Side-effecting Operations
Side-effecting operations
• forEach, forEachOrdered



people.stream()

.forEach(System.out::println);
• So could we calculate total ages like this?



int sum = 0;

people.stream()

.mapToInt(Person::getAge)

.forEach(a -> { sum += a });
people.stream()

.forEach(System.out::println);

int sum = 0;

people.stream()

.mapToInt(Person::getAge)

.forEach(a -> { sum += a; });

Journey’s End, JavaOne, September 2016
Side-effecting Operations
Side-effecting operations
• forEach, forEachOrdered



people.stream()

.forEach(System.out::println);
• So could we calculate total ages like this?



int sum = 0;

people.stream()

.mapToInt(Person::getAge)

.forEach(a -> { sum += a });
people.stream()

.forEach(System.out::println);

int sum = 0;

people.stream()

.mapToInt(Person::getAge)

.forEach(a -> { sum += a; });

Don’t do this!
Journey’s End, JavaOne, September 2016
• Using an accumulator:
Reduction – Why?
int[] vals = new int[100];
Arrays.setAll(vals, i -> i);
int sum = 0;
for (int i = 0 ; i < vals.length ; i++) {
sum += vals[i];
}

Journey’s End, JavaOne, September 2016
• Using an accumulator:
Reduction – Why?
int[] vals = new int[100];
Arrays.setAll(vals, i -> i);
int sum = 0;
for (int i = 0 ; i < vals.length ; i++) {
sum += vals[i];
}

0 1 2 3
+
+
+
Journey’s End, JavaOne, September 2016
• Avoiding an accumulator:
Reduction – Why?
Journey’s End, JavaOne, September 2016
• Avoiding an accumulator:
Reduction – Why?
Journey’s End, JavaOne, September 2016
• Avoiding an accumulator:
Reduction – Why?
int[] vals = new int[100];
Arrays.setAll(vals, i -> i);
OptionalInt sum = Arrays.stream(vals)
.reduce((a,b) -> a + b);

+ +
+
1 2 30
Journey’s End, JavaOne, September 2016
• Avoiding an accumulator:
Reduction – Why?
int[] vals = new int[100];
Arrays.setAll(vals, i -> i);
OptionalInt sum = Arrays.stream(vals)
.reduce((a,b) -> a + b);

+ +
+
1 2 30
+
+
+
Journey’s End, JavaOne, September 2016
• Avoiding an accumulator:
Reduction – Why?
int[] vals = new int[100];
Arrays.setAll(vals, i -> i);
OptionalInt sum = Arrays.stream(vals)
.reduce((a,b) -> a + b);

BinaryOperator must be associative!
+ +
+
1 2 30
+
+
+
Journey’s End, JavaOne, September 2016
• Avoiding an accumulator:
Reduction – Why?
int[] vals = new int[100];
Arrays.setAll(vals, i -> i);
OptionalInt sum = Arrays.stream(vals)
.reduce((a,b) -> a + b);

BinaryOperator must be associative!
a + (b + c) = (a + b) + c
+ +
+
1 2 30
+
+
+
Journey’s End, JavaOne, September 2016
0 1 2 3 4 5 6 7
+ +
+
+
+
+
+
Reduction – Why?
Journey’s End, JavaOne, September 2016
0 1 2 3 4 5 6 7
+ +
+
+
+
+
+
Reduction – Why?
Journey’s End, JavaOne, September 2016
0 1 2 3 4 5 6 7
+ +
+
+
+
+
+
Intermediate operations
Reduction – Why?
Journey’s End, JavaOne, September 2016
Reduction on ImmutableValues
Reduction works on immutable values too
BigDecimal[] vals = new BigDecimal[100];
Arrays.setAll(vals, i -> new BigDecimal(i));
Optional<BigDecimal> sum = Arrays.stream(vals)
.reduce(BigDecimal::add);

Journey’s End, JavaOne, September 2016
Reduction to Collections?
Journey’s End, JavaOne, September 2016
Reduction to Collections?
This also works with collections – sort of ...
• for each element, client code creates a new empty
collection and adds the single element to it
• combines collections using addAll
Journey’s End, JavaOne, September 2016
Reduction to Collections?
This also works with collections – sort of ...
• for each element, client code creates a new empty
collection and adds the single element to it
• combines collections using addAll
We can do better!
Journey’s End, JavaOne, September 2016
Reduction over an Identity
BigDecimal[] vals = new BigDecimal[100];
Arrays.setAll(vals, i -> new BigDecimal(i));
BigDecimal sum = Arrays.stream(vals)
.reduce(BigDecimal.ZERO,BigDecimal::add);

Journey’s End, JavaOne, September 2016
Reduction over an Identity
BigDecimal[] vals = new BigDecimal[100];
Arrays.setAll(vals, i -> new BigDecimal(i));
BigDecimal sum = Arrays.stream(vals)
.reduce(BigDecimal.ZERO,BigDecimal::add);

Works for immutable objects:
Journey’s End, JavaOne, September 2016
Reduction over an Identity
+
+
+
0 1 2 3
+
+
+
0
4 5 6 7
0
++
+
Journey’s End, JavaOne, September 2016
Reduction to Collections?
Journey’s End, JavaOne, September 2016
Reduction to Collections?
Reduction over an identity doesn’t work with
collections at all
• reduction reuses the identity element
Journey’s End, JavaOne, September 2016
Reduction to Collections?
Reduction over an identity doesn’t work with
collections at all
• reduction reuses the identity element
We’ve got to do better!
Journey’s End, JavaOne, September 2016
The Answer – Collectors
a
a
a
e0 e1 e2 e3
a
a
a
e4 e5 e6 e7
aa
c
Journey’s End, JavaOne, September 2016
The Answer – Collectors
a
a
a
e0 e1 e2 e3
a
a
a
() -> []
e4 e5 e6 e7
aa
c
() -> []
Journey’s End, JavaOne, September 2016
The Answer – Collectors
a
a
a
e0 e1 e2 e3
a
a
a
() -> []
e4 e5 e6 e7
aa
c
a: accumulator
c: combiner
() -> []
Journey’s End, JavaOne, September 2016
Collectors
Journey’s End, JavaOne, September 2016
Collectors
So to define a collector, you need to provide
• Supplier
• Accumulator
• Combiner
Journey’s End, JavaOne, September 2016
Collectors
So to define a collector, you need to provide
• Supplier
• Accumulator
• Combiner
That sounds really hard!
Journey’s End, JavaOne, September 2016
Collectors
So to define a collector, you need to provide
• Supplier
• Accumulator
• Combiner
That sounds really hard!
Good then that we don’t have to do it
… very often
Journey’s End, JavaOne, September 2016
• Why collectors?
• Using the predefined collectors
• Worked problems
• Writing your own
Journey’s End – Agenda
Journey’s End, JavaOne, September 2016
Collectors API
Factory methods in the Collectors class.They
produce standalone collectors, accumulating to:
• framework-supplied containers
• custom collections
• classification maps
Journey’s End, JavaOne, September 2016
Predefined Standalone Collectors – from factory
methods in Collectors class
• toList(), toSet(), toMap(), joining()
• toMap(), toCollection()
• groupingBy(), partitioningBy(),
groupingByConcurrent()
Using the Predefined Collectors
Journey’s End, JavaOne, September 2016
Predefined Standalone Collectors – from factory
methods in Collectors class
• toList(), toSet(), toMap(), joining()
• toMap(), toCollection()
• groupingBy(), partitioningBy(),
groupingByConcurrent()
Using the Predefined Collectors
framework provides
the Supplier
Journey’s End, JavaOne, September 2016
Predefined Standalone Collectors – from factory
methods in Collectors class
• toList(), toSet(), toMap(), joining()
• toMap(), toCollection()
• groupingBy(), partitioningBy(),
groupingByConcurrent()
Using the Predefined Collectors
user provides
the Supplier
framework provides
the Supplier
Journey’s End, JavaOne, September 2016
Predefined Standalone Collectors – from factory
methods in Collectors class
• toList(), toSet(), toMap(), joining()
• toMap(), toCollection()
• groupingBy(), partitioningBy(),
groupingByConcurrent()
Using the Predefined Collectors
user provides
the Supplier
framework provides
the Supplier
produce a 

classification map
Journey’s End, JavaOne, September 2016
Simple Collector – toSet()
Collectors.toSet()
people.stream().collect(Collectors.toSet())
Journey’s End, JavaOne, September 2016
Simple Collector – toSet()
Stream<Person>
Collectors.toSet()
Set<Person>
people.stream().collect(Collectors.toSet())
Collector<Person,?,Set<Person>>
Journey’s End, JavaOne, September 2016
Simple Collector – toSet()
Stream<Person>
Collectors.toSet()
Set<Person>
people.stream().collect(Collectors.toSet())
bill
Collector<Person,?,Set<Person>>
Journey’s End, JavaOne, September 2016
Simple Collector – toSet()
Stream<Person>
Collectors.toSet()
Set<Person>
people.stream().collect(Collectors.toSet())
bill
Collector<Person,?,Set<Person>>
Journey’s End, JavaOne, September 2016
Simple Collector – toSet()
Stream<Person>
Collectors.toSet()
Set<Person>
people.stream().collect(Collectors.toSet())
bill
Collector<Person,?,Set<Person>>
Journey’s End, JavaOne, September 2016
Simple Collector – toSet()
Stream<Person>
Collectors.toSet()
Set<Person>
people.stream().collect(Collectors.toSet())
bill
jon
Collector<Person,?,Set<Person>>
Journey’s End, JavaOne, September 2016
Simple Collector – toSet()
Stream<Person>
Collectors.toSet()
Set<Person>
people.stream().collect(Collectors.toSet())
bill
jon
Collector<Person,?,Set<Person>>
Journey’s End, JavaOne, September 2016
Simple Collector – toSet()
Stream<Person>
Collectors.toSet()
Set<Person>
people.stream().collect(Collectors.toSet())
amy
bill
jon
Collector<Person,?,Set<Person>>
Journey’s End, JavaOne, September 2016
Simple Collector – toSet()
Stream<Person>
Collectors.toSet()
Set<Person>
people.stream().collect(Collectors.toSet())
amy
bill
jon
Collector<Person,?,Set<Person>>
Journey’s End, JavaOne, September 2016
Simple Collector – toSet()
Collectors.toSet()
Set<Person>
people.stream().collect(Collectors.toSet())
amy
bill
jon
Collector<Person,?,Set<Person>>
Journey’s End, JavaOne, September 2016
Simple Collector – toSet()
Collectors.toSet()
Set<Person>
{ , , }
people.stream().collect(Collectors.toSet())
amybilljon
Collector<Person,?,Set<Person>>
Journey’s End, JavaOne, September 2016
toMap(Function<T,K> keyMapper,
Function<T,U> valueMapper)
people.stream().collect(
Collectors.toMap(
Person::getCity,

Person::getName))
Journey’s End, JavaOne, September 2016
toMap(Function<T,K> keyMapper,
Function<T,U> valueMapper)
Stream<Person>
toMap() Map<City,String>
Collector<Person,?,Map<City,String>
people.stream().collect(toMap(Person::getCity,Person::getName))
Journey’s End, JavaOne, September 2016
toMap(Function<T,K> keyMapper,
Function<T,U> valueMapper)
Stream<Person>
toMap() Map<City,String>
Collector<Person,?,Map<City,String>
Journey’s End, JavaOne, September 2016
toMap(Function<T,K> keyMapper,
Function<T,U> valueMapper)
Stream<Person>
toMap() Map<City,String>
bill
Journey’s End, JavaOne, September 2016
toMap(Function<T,K> keyMapper,
Function<T,U> valueMapper)
Stream<Person>
toMap() Map<City,String>
bill
Person::getCity
Journey’s End, JavaOne, September 2016
toMap(Function<T,K> keyMapper,
Function<T,U> valueMapper)
Stream<Person>
toMap() Map<City,String>
London
bill
Journey’s End, JavaOne, September 2016
toMap(Function<T,K> keyMapper,
Function<T,U> valueMapper)
Stream<Person>
toMap() Map<City,String>
London
bill Person::getName
Journey’s End, JavaOne, September 2016
toMap(Function<T,K> keyMapper,
Function<T,U> valueMapper)
Stream<Person>
toMap() Map<City,String>
London “Bill”
bill Person::getName
Journey’s End, JavaOne, September 2016
toMap(Function<T,K> keyMapper,
Function<T,U> valueMapper)
Stream<Person>
toMap() Map<City,String>
London “Bill”
Journey’s End, JavaOne, September 2016
toMap(Function<T,K> keyMapper,
Function<T,U> valueMapper)
Stream<Person>
toMap() Map<City,String>
amy
London “Bill”
Journey’s End, JavaOne, September 2016
toMap(Function<T,K> keyMapper,
Function<T,U> valueMapper)
Stream<Person>
toMap() Map<City,String>
Athens
amy
London “Bill”
Journey’s End, JavaOne, September 2016
toMap(Function<T,K> keyMapper,
Function<T,U> valueMapper)
Stream<Person>
toMap() Map<City,String>
“Amy”Athens
London “Bill”
Journey’s End, JavaOne, September 2016
toMap(Function<T,K> keyMapper,
Function<T,U> valueMapper)
Stream<Person>
toMap() Map<City,String>
“Amy”Athens
jon
London “Bill”
Journey’s End, JavaOne, September 2016
toMap(Function<T,K> keyMapper,
Function<T,U> valueMapper)
Stream<Person>
toMap() Map<City,String>
“Amy”Athens
London “Bill”
Tulsa “Jon”
Journey’s End, JavaOne, September 2016
toMap(Function<T,K> keyMapper,
Function<T,U> valueMapper)
toMap() Map<City,String>
“Amy”Athens
London “Bill”
Tulsa “Jon”
Journey’s End, JavaOne, September 2016
toMap(Function<T,K> keyMapper,
Function<T,U> valueMapper)
toMap() Map<City,String>
“Amy”Athens
London “Bill”
Tulsa “Jon”
Journey’s End, JavaOne, September 2016
toMap(Function<T,K> keyMapper,
Function<T,U> valueMapper)
Stream<Person>
toMap() Map<City,String>
Journey’s End, JavaOne, September 2016
toMap(Function<T,K> keyMapper,
Function<T,U> valueMapper)
Stream<Person>
toMap() Map<City,String>
“Amy”Athens
jon
London “Bill”
Journey’s End, JavaOne, September 2016
toMap(Function<T,K> keyMapper,
Function<T,U> valueMapper)
Stream<Person>
toMap() Map<City,String>
“Amy”Athens
jon
London “Bill”
Athens
Journey’s End, JavaOne, September 2016
toMap(Function<T,K> keyMapper,
Function<T,U> valueMapper)
Stream<Person>
toMap() Map<City,String>
“Amy”Athens
jon
London
IllegalStateException
“Bill”
Athens
Journey’s End, JavaOne, September 2016
toMap(Function<T,K> keyMapper,
Function<T,U> valueMapper
BinaryOperator<U> mergeFunction)
people.stream().collect(
Collectors.toMap(
Person::getCity,

Person::getName,
(a,b) -> a.concat(b)))
Journey’s End, JavaOne, September 2016
toMap(Function<T,K> keyMapper,
Function<T,U> valueMapper
BinaryOperator<U> mergeFunction)
Stream<Person>
toMap() Map<City,String>
Journey’s End, JavaOne, September 2016
toMap(Function<T,K> keyMapper,
Function<T,U> valueMapper
BinaryOperator<U> mergeFunction)
Stream<Person>
toMap() Map<City,String>
“Amy”Athens
London “Bill”
Athens
Journey’s End, JavaOne, September 2016
toMap(Function<T,K> keyMapper,
Function<T,U> valueMapper
BinaryOperator<U> mergeFunction)
Stream<Person>
toMap() Map<City,String>
“Amy”Athens
London “Bill”
Athens
Journey’s End, JavaOne, September 2016
toMap(Function<T,K> keyMapper,
Function<T,U> valueMapper
BinaryOperator<U> mergeFunction)
Stream<Person>
toMap() Map<City,String>
“Amy”Athens
London “Bill”
“Jon”
Athens
Journey’s End, JavaOne, September 2016
toMap(Function<T,K> keyMapper,
Function<T,U> valueMapper
BinaryOperator<U> mergeFunction)
Stream<Person>
toMap() Map<City,String>
“Amy”Athens
London “Bill”
“Jon”
(a,b) -> a.concat(b)
Athens
Journey’s End, JavaOne, September 2016
toMap(Function<T,K> keyMapper,
Function<T,U> valueMapper
BinaryOperator<U> mergeFunction)
Stream<Person>
toMap() Map<City,String>
Athens
London “Bill”
(a,b) -> a.concat(b)
“AmyJon”
Athens
Journey’s End, JavaOne, September 2016
Collectors API
Factory methods in the Collectors class.They
produce standalone collectors, accumulating to:
• framework-supplied containers
• custom collections
• classification maps
Journey’s End, JavaOne, September 2016
toMap(Function<T,K> keyMapper,
Function<T,U> valueMapper
BinaryOperator<U> mergeFunction)
toMap(Function<T,K> keyMapper,
Function<T,U> valueMapper
BinaryOperator<U> mergeFunction,
Supplier<M> mapFactory)
people.stream().collect(
Collectors.toMap(
Person::getCity,

Person::getName,
(a,b) -> a.concat(b),

TreeMap::new))
Journey’s End, JavaOne, September 2016
toMap(Function<T,K> keyMapper,
Function<T,U> valueMapper
BinaryOperator<U> mergeFunction,
Supplier<M> mapFactory)
Stream<Person>
toMap() Map<City,String>
Journey’s End, JavaOne, September 2016
toMap(Function<T,K> keyMapper,
Function<T,U> valueMapper
BinaryOperator<U> mergeFunction,
Supplier<M> mapFactory)
Stream<Person>
toMap() Map<City,String>
Journey’s End, JavaOne, September 2016
Collecting to Custom Collections
Journey’s End, JavaOne, September 2016
Collecting to Custom Collections
toCollection(Supplier<C> collectionFactory)
Journey’s End, JavaOne, September 2016
Collecting to Custom Collections
<C extends Collection<T>>
toCollection(Supplier<C> collectionFactory)
Journey’s End, JavaOne, September 2016
Collecting to Custom Collections
returns
Collector<T,?,C>
<C extends Collection<T>>
toCollection(Supplier<C> collectionFactory)
Journey’s End, JavaOne, September 2016
Collecting to Custom Collections
returns
Collector<T,?,C>
<C extends Collection<T>>
NavigableSet<String> sortedNames = people.stream()
.map(Person::getName)

.collect(toCollection(TreeSet::new));
toCollection(Supplier<C> collectionFactory)
Journey’s End, JavaOne, September 2016
Collectors API
Factory methods in the Collectors class.They
produce standalone collectors, accumulating to:
• framework-supplied containers
• custom collections
• classification maps
Journey’s End, JavaOne, September 2016
Collecting to Classification Maps
groupingBy
• simple
• with downstream
• with downstream and map factory
partitioningBy
Journey’s End, JavaOne, September 2016
groupingBy(Function<T,K> classifier)
Uses the classifier function to make a classification mapping
Like toMap(), except that the values placed in the map are lists of
the elements, one List corresponding to each classification key:
For example, use Person.getCity() to make a Map<City,List<Person>>
Map<City,List<Person>> peopleByCity = people.stream()
.collect(Collectors.groupingBy(Person::getCity));
Journey’s End, JavaOne, September 2016
Stream<Person>
groupingBy() Map<City,List<Person>>
bill
jon
amy Athens
London
Collector<Person,?,Map<City,List<Person>
groupingBy(Function<Person,City>)
Classifier
Person→City
Journey’s End, JavaOne, September 2016
Stream<Person>
groupingBy() Map<City,List<Person>>
bill
jon
amy Athens
London
groupingBy(Function<Person,City>)
Journey’s End, JavaOne, September 2016
Stream<Person>
groupingBy() Map<City,List<Person>>
bill
jon
amy Athens
bill London
groupingBy(Function<Person,City>)
Journey’s End, JavaOne, September 2016
Stream<Person>
groupingBy() Map<City,List<Person>>
bill
jon
amy Athens
billLondon
groupingBy(Function<Person,City>)
[ ]
Journey’s End, JavaOne, September 2016
Stream<Person>
groupingBy() Map<City,List<Person>>
bill
jon
amy Athens [ ]
bill
amy
London
groupingBy(Function<Person,City>)
[ ]
Journey’s End, JavaOne, September 2016
Stream<Person>
groupingBy() Map<City,List<Person>>
bill
jon
amy Athens [ ]
[ , ]bill
amy
jonLondon
groupingBy(Function<Person,City>)
Journey’s End, JavaOne, September 2016
groupingBy() Map<City,List<Person>>
bill
jon
amy Athens [ ]
[ , ]bill
amy
jonLondon
groupingBy(Function<Person,City>)
Journey’s End, JavaOne, September 2016
groupingBy() Map<City,List<Person>>
bill
jon
amy
Athens [ ]
[ , ]bill
amy
jonLondon
groupingBy(Function<Person,City>)
Journey’s End, JavaOne, September 2016
groupingBy(Function<T,K> classifier)
Uses the classifier function to make a classification mapping
Like toMap(), except that the values placed in the map are lists of
the elements, one List corresponding to each classification key:
For example, use Person.getCity() to make a Map<City,List<Person>>
Map<City,List<Person>> peopleByCity = people.stream()
.collect(Collectors.groupingBy(Person::getCity));
Journey’s End, JavaOne, September 2016
groupingBy(classifier, downstream)
Uses the classifier function to make a classification mapping into a
container defined by a downstream Collector
Like toMap(), except that the values placed in the map are containers
of the elements, one container corresponding to each classification key:
For example, use Person.getCity() to make a Map<City,Set<Person>>
Map<City,List<Person>> peopleByCity = people.stream()
.collect(Collectors.groupingBy(Person::getCity,toSet()));
Journey’s End, JavaOne, September 2016
groupingBy(Function classifier,Collector downstream))
Stream<Person>
groupingBy()
Map<City,Set<Person>
bill
jon
amy
London
Athens
Downstream
Collector
—
toSet()
Stream<Person
>
Classifier
Person→City
Journey’s End, JavaOne, September 2016
groupingBy(Function classifier,Collector downstream))
Stream<Person>
groupingBy()
Map<City,Set<Person>
bill
jon
amy
London
Athens
Journey’s End, JavaOne, September 2016
groupingBy(Function classifier,Collector downstream))
Stream<Person>
groupingBy()
Map<City,Set<Person>
bill
jon
amy
London
Athens
bill
Journey’s End, JavaOne, September 2016
groupingBy(Function classifier,Collector downstream))
Stream<Person>
groupingBy()
Map<City,Set<Person>
bill
jon
amy
London
Athens
bill
Journey’s End, JavaOne, September 2016
groupingBy(Function classifier,Collector downstream))
Stream<Person>
groupingBy()
Map<City,Set<Person>
bill
jon
amy
London
Athens
bill
Journey’s End, JavaOne, September 2016
groupingBy(Function classifier,Collector downstream))
Stream<Person>
groupingBy()
Map<City,Set<Person>
bill
jon
amy
London
Athensamy
bill
Journey’s End, JavaOne, September 2016
groupingBy(Function classifier,Collector downstream))
Stream<Person>
groupingBy()
Map<City,Set<Person>
bill
jon
amy
London
Athens amy
bill
Journey’s End, JavaOne, September 2016
groupingBy(Function classifier,Collector downstream))
Stream<Person>
groupingBy()
Map<City,Set<Person>
bill
jon
amy
London
Athens amy
bill
Journey’s End, JavaOne, September 2016
groupingBy(Function classifier,Collector downstream))
Stream<Person>
groupingBy()
Map<City,Set<Person>
bill
jon
amy
London
Athens amy
jon bill
Journey’s End, JavaOne, September 2016
groupingBy(Function classifier,Collector downstream))
Stream<Person>
groupingBy()
Map<City,Set<Person>
bill
jon
amy
London
Athens amy
jon
bill
Journey’s End, JavaOne, September 2016
groupingBy(Function classifier,Collector downstream))
groupingBy()
Map<City,Set<Person>
bill
jon
amy
London
Athens amy
jon
bill
Journey’s End, JavaOne, September 2016
groupingBy(Function classifier,Collector downstream))
groupingBy()
Map<City,Set<Person>
bill
jon
amy
London
Athens amy
jon
bill
Journey’s End, JavaOne, September 2016
groupingBy(Function classifier,Collector downstream))
groupingBy()
Map<City,Set<Person>
bill
jon
amy
London
Athens { }amy
{ , }jonbill
Journey’s End, JavaOne, September 2016
groupingBy(Function classifier,Collector downstream))
groupingBy()
Map<City,Set<Person>
bill
jon
amy
London
Athens { }amy
{ , }jonbill
Journey’s End, JavaOne, September 2016
mapping(Function mapper,Collector downstream))
Applies a mapping function to each input element before passing it
to the downstream collector.
Journey’s End, JavaOne, September 2016
mapping(Function mapper,Collector downstream))
Applies a mapping function to each input element before passing it
to the downstream collector.
Set<City> inhabited = people.stream()

.collect(mapping(Person::getCity,toSet()));
Animation example
Journey’s End, JavaOne, September 2016
mapping(Function mapper,Collector downstream))
LondonStream<Person>
mapping()
bill
jon
amy Athens
Mapper
Person→City
Downstream
Collector
—
toSet()
Stream<City>
Set<City>
Journey’s End, JavaOne, September 2016
mapping(Function mapper,Collector downstream))
LondonStream<Person>
mapping()
bill
jon
amy Athens
Set<City>
Journey’s End, JavaOne, September 2016
mapping(Function mapper,Collector downstream))
LondonStream<Person>
mapping()
bill
jon
amy Athens
London
Set<City>
Journey’s End, JavaOne, September 2016
mapping(Function mapper,Collector downstream))
LondonStream<Person>
mapping()
bill
jon
amy Athens
Athens
London
Set<City>
Journey’s End, JavaOne, September 2016
mapping(Function mapper,Collector downstream))
LondonStream<Person>
mapping()
bill
jon
amy Athens
Athens
LondonLondon
Set<City>
Journey’s End, JavaOne, September 2016
mapping(Function mapper,Collector downstream))
London
mapping()
bill
jon
amy Athens
Athens
LondonLondon
Set<City>
Journey’s End, JavaOne, September 2016
mapping(Function mapper,Collector downstream))
London
mapping()
bill
jon
amy
{ ,
}
Athens
Athens
London
Set<City>
Journey’s End, JavaOne, September 2016
mapping(Function mapper,Collector downstream))
London
mapping()
bill
jon
amy
{ ,
}
Athens
Athens
London
Set<City>
Journey’s End, JavaOne, September 2016
mapping(Function mapper,Collector downstream))
Applies a mapping function to each input element before passing it
to the downstream collector.
Set<City> inhabited = people.stream()

.collect(mapping(Person::getCity,toSet()));
Animation example
Journey’s End, JavaOne, September 2016
mapping(Function mapper,Collector downstream))
Applies a mapping function to each input element before passing it
to the downstream collector.
Set<City> inhabited = people.stream()

.collect(mapping(Person::getCity,toSet()));
Map<City,String> namesByCity = people.stream()

.collect(groupingBy(Person::getCity,
mapping(Person::getName,joining()));
Animation example
Sensible example
Collectors’ Fair, JavaOne, October 2016
groupingBy()
bill
jon
amy Athens
billamyjon
London
Collector<Person,?,String>
Classifier
Person→City
JDK Collectors with Java 8 Streams
mapping()
Mapper
Person→String
Stream<String>
joining()
Collector<CharSequence,?,String>
Journey’s End, JavaOne, September 2016
Dualling Convenience Reductions
Terminal operation Collectors factory method
count() counting()
max()
min()
maxBy()
minBy()
sum()
average()
summingXxx()
averagingXxx()
summaryStatistics() summarizingXxx()
reduce(accumulator)
reduce(identity, accumulator)
reduce(identity, accumulator, combiner)
reducing(accumulator)
reducing(identity, accumulator)
reducing(identity, accumulator, combiner)
Journey’s End, JavaOne, September 2016
Concurrent Collection
Journey’s End, JavaOne, September 2016
Concurrent Collection
Journey’s End, JavaOne, September 2016
Thread safety is guaranteed by the framework
• Even for non-threadsafe containers!
Concurrent Collection
Journey’s End, JavaOne, September 2016
Thread safety is guaranteed by the framework
• Even for non-threadsafe containers!
But at a price... So what if your container is already threadsafe?
• A concurrentMap implementation, for example?
Concurrent Collection
Journey’s End, JavaOne, September 2016
Thread safety is guaranteed by the framework
• Even for non-threadsafe containers!
But at a price... So what if your container is already threadsafe?
• A concurrentMap implementation, for example?
Concurrent Collection
Journey’s End, JavaOne, September 2016
Thread safety is guaranteed by the framework
• Even for non-threadsafe containers!
But at a price... So what if your container is already threadsafe?
• A concurrentMap implementation, for example?
Every overload of toMap() and groupingBy() has a dual
• toConcurrentMap(...)
• groupingByConcurrent(...)
Concurrent Collection
Journey’s End, JavaOne, September 2016
• Why collectors?
• Using the predefined collectors
• Worked problems
• Writing your own
Journey’s End – Agenda
Most Popular Age
Most Popular Age
Optional<Integer> modalAge = populationByAge
Most Popular Age
Optional<Integer> modalAge = populationByAge
.entrySet()
Most Popular Age
Optional<Integer> modalAge = populationByAge
.entrySet()
.stream()
Most Popular Age
Optional<Integer> modalAge = populationByAge
.entrySet()
.stream()
.sorted(Entry.<Integer,Long>comparingByValue().reversed())
Most Popular Age
Optional<Integer> modalAge = populationByAge
.entrySet()
.stream()
.sorted(Entry.<Integer,Long>comparingByValue().reversed())
.map(Entry::getKey)
Most Popular Age
Optional<Integer> modalAge = populationByAge
.entrySet()
.stream()
.sorted(Entry.<Integer,Long>comparingByValue().reversed())
.map(Entry::getKey)
.findFirst();
Most Popular Age
Most Popular Age
Optional<Integer> modalAge = populationByAge
Most Popular Age
Optional<Integer> modalAge = populationByAge
.entrySet()
Most Popular Age
Optional<Integer> modalAge = populationByAge
.entrySet()
.stream()
Most Popular Age
Optional<Integer> modalAge = populationByAge
.entrySet()
.stream()
.collect(maxBy(Comparator.comparing(Map.Entry::getValue)))
Most Popular Age
Optional<Integer> modalAge = populationByAge
.entrySet()
.stream()
.collect(maxBy(Comparator.comparing(Map.Entry::getValue)))
.map(Map.Entry::getKey);
Most Popular Age
Optional<Integer> modalAge = populationByAge
.entrySet()
.stream()
.collect(maxBy(Comparator.comparing(Map.Entry::getValue)))
.map(Map.Entry::getKey);
Map<Long, Set<Integer>> collect = people.stream()
.collect(groupingBy(People::getAge, counting()))
.entrySet()
.stream()
.collect(groupingBy(Entry::getValue,
mapping(Entry::getKey, toSet())));
Most Popular Ages
Journey’s End, JavaOne, September 2016
• Why collectors?
• Using the predefined collectors
• Worked problems
• Writing your own
Journey’s End – Agenda
Journey’s End, JavaOne, September 2016
Writing a Collector
Journey’s End, JavaOne, September 2016
Writing a Collector
Why would you want to?
Journey’s End, JavaOne, September 2016
Writing a Collector
Why would you want to?
• accumulate to a container that doesn’t implement Collection
Journey’s End, JavaOne, September 2016
Writing a Collector
Why would you want to?
• accumulate to a container that doesn’t implement Collection
• share state between values being collected
Journey’s End, JavaOne, September 2016
Oprah’s Problem
Journey’s End, JavaOne, September 2016
Oprah’s Problem
How to find a book?
Journey’s End, JavaOne, September 2016
Oprah’s Problem
How to find a book?
336
640
144
624
Page count 239
640
384
1104
172
400
Journey’s End, JavaOne, September 2016
What Oprah Needs
New Earth 0
Poisonwood Bible 336
Night 976
A Fine Balance 1120
...
Cumulative
page counts
Journey’s End, JavaOne, September 2016
Supplier and Accumulator
“NE” 336 0 “PB” 640 336[ ],
]“NE” 336 0[
][
aNewEarth thePoisonwoodBible
accumulator
accumulator
Journey’s End, JavaOne, September 2016
Combiner
,“Night” 144 976 “AFB” 624 1120 ]“NE” 336 0 “PB” 640 336[ , ,
Journey’s End, JavaOne, September 2016
Combiner
,“Night” 144 0[ “AFB” 624 144 ]“NE” 336 0 “PB” 640 336[ ],
,“Night” 144 976 “AFB” 624 1120 ]“NE” 336 0 “PB” 640 336[ , ,
Journey’s End, JavaOne, September 2016
Combiner
combiner
,“Night” 144 0[ “AFB” 624 144 ]“NE” 336 0 “PB” 640 336[ ],
,“Night” 144 976 “AFB” 624 1120 ]“NE” 336 0 “PB” 640 336[ , ,
Journey’s End, JavaOne, September 2016
Combiner
combiner
,“Night” 144 0[ “AFB” 624 144 ]“NE” 336 0 “PB” 640 336[ ],
,“Night” 144 976 “AFB” 624 1120 ]“NE” 336 0 “PB” 640 336[ , ,
976
Journey’s End, JavaOne, September 2016
Combiner
combiner
,“Night” 144 0[ “AFB” 624 144 ]“NE” 336 0 “PB” 640 336[ ],
,“Night” 144 976 “AFB” 624 1120 ]“NE” 336 0 “PB” 640 336[ , ,
976
Journey’s End, JavaOne, September 2016
Combiner
combiner
,“Night” 144 0[ “AFB” 624 144 ]“NE” 336 0 “PB” 640 336[ ],
,“Night” 144 976 “AFB” 624 1120 ]“NE” 336 0 “PB” 640 336[ , ,
Journey’s End, JavaOne, September 2016
Using Reduction Instead...
“New Earth” 336 0 “Poisonwood Bible” 640 336[ , “Night” 144 976, ]
newEarth poisonwood night
Journey’s End, JavaOne, September 2016
Using Reduction Instead...
“New Earth” 336 0 “Poisonwood Bible” 640 336[ , “Night” 144 976, ]
newEarth poisonwood night
Page count
Start displacement
Journey’s End, JavaOne, September 2016
Using Reduction Instead...
“New Earth” 336 0 “Poisonwood Bible” 640 336[ , “Night” 144 976, ]
]“New Earth” 336 0 “Poisonwood Bible” 640 0[ ] ]“Night” 144 0 ][[
newEarth poisonwood night
Journey’s End, JavaOne, September 2016
Using Reduction Instead...
“New Earth” 336 0 “Poisonwood Bible” 640 336[ , “Night” 144 976, ]
]“New Earth” 336 0 “Poisonwood Bible” 640 0[ ] ]“Night” 144 0 ][[
newEarth poisonwood night
Map
Journey’s End, JavaOne, September 2016
Using Reduction Instead...
“New Earth” 336 0 “Poisonwood Bible” 640 336[ , “Night” 144 976, ]
]“New Earth” 336 0 “Poisonwood Bible” 640 0[ ] ]“Night” 144 0 ][[
newEarth poisonwood night
Reduce
Map
Journey’s End, JavaOne, September 2016
Using Reduction Instead...
“New Earth” 336 0 “Poisonwood Bible” 640 336[ , “Night” 144 976, ]
]“New Earth” 336 0 “Poisonwood Bible” 640 0[ ] ]“Night” 144 0 ][[
PartialResult::new
ArrayDeque::new
newEarth poisonwood night
Reduce
Map
Journey’s End, JavaOne, September 2016
Using Reduction Instead...
“New Earth” 336 0 “Poisonwood Bible” 640 336[ , “Night” 144 976, ]
]“New Earth” 336 0 “Poisonwood Bible” 640 0[ ] ]“Night” 144 0 ][[
PartialResult::new
ArrayDeque::new
PartialResult::new
ArrayDeque::new
PartialResult::new
ArrayDeque::new
newEarth poisonwood night
Reduce
Journey’s End, JavaOne, September 2016
Performance of Collectors
Depends on the performance of accumulator and combiner
functions
• toList(), toSet(), toCollection – performance will probably be
dominated by accumulator, but remember that the framework will
need to manage multithread access to non-threadsafe containers
for the combine operation
toMap(), toConcurrentMap()
• map merging is slow. Resizing maps, especially concurrent maps, is
particularly expensive.Whenever possible, presize all data
structures, maps in particular.
Journey’s End, JavaOne, September 2016
Conclusion
Collectors
• generalisation of reduction
• allow a functional style while continuing to work with a
language based on mutation
• designed for composition
• flexible and powerful programming tool
• take a bit of getting used to! – but they’re worth it!
Journey’s End, JavaOne, September 2016
Questions?
Journey’s End, JavaOne, September 2016
Questions?

Más contenido relacionado

Destacado (6)

Journey’s End
Journey’s EndJourney’s End
Journey’s End
 
Journey’s end
Journey’s end Journey’s end
Journey’s end
 
Journey’s end exam practice
Journey’s end exam practiceJourney’s end exam practice
Journey’s end exam practice
 
Journey’s end structure
Journey’s end   structureJourney’s end   structure
Journey’s end structure
 
Journey’s end presentation
Journey’s end presentationJourney’s end presentation
Journey’s end presentation
 
Journey’S End Exam Prep
Journey’S End Exam PrepJourney’S End Exam Prep
Journey’S End Exam Prep
 

Similar a Journey's end

Single Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and JasmineSingle Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and Jasmine
Paulo Ragonha
 
Taxonomy of Scala
Taxonomy of ScalaTaxonomy of Scala
Taxonomy of Scala
shinolajla
 

Similar a Journey's end (20)

Journey's End – Collection and Reduction in the Stream API
Journey's End – Collection and Reduction in the Stream APIJourney's End – Collection and Reduction in the Stream API
Journey's End – Collection and Reduction in the Stream API
 
Good and Wicked Fairies, and the Tragedy of the Commons: Understanding the Pe...
Good and Wicked Fairies, and the Tragedy of the Commons: Understanding the Pe...Good and Wicked Fairies, and the Tragedy of the Commons: Understanding the Pe...
Good and Wicked Fairies, and the Tragedy of the Commons: Understanding the Pe...
 
Graal in GraalVM - A New JIT Compiler
Graal in GraalVM - A New JIT CompilerGraal in GraalVM - A New JIT Compiler
Graal in GraalVM - A New JIT Compiler
 
Scala.js
Scala.jsScala.js
Scala.js
 
Kpi driven-java-development
Kpi driven-java-developmentKpi driven-java-development
Kpi driven-java-development
 
Single Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and JasmineSingle Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and Jasmine
 
Everything-as-code. A polyglot journey.
Everything-as-code. A polyglot journey.Everything-as-code. A polyglot journey.
Everything-as-code. A polyglot journey.
 
Everything-as-code - a polyglot journey.
Everything-as-code - a polyglot journey.Everything-as-code - a polyglot journey.
Everything-as-code - a polyglot journey.
 
Functor, Apply, Applicative And Monad
Functor, Apply, Applicative And MonadFunctor, Apply, Applicative And Monad
Functor, Apply, Applicative And Monad
 
Using Spring with Scala
Using Spring with ScalaUsing Spring with Scala
Using Spring with Scala
 
Scala in Places API
Scala in Places APIScala in Places API
Scala in Places API
 
RxSwift to Combine
RxSwift to CombineRxSwift to Combine
RxSwift to Combine
 
[Start] Scala
[Start] Scala[Start] Scala
[Start] Scala
 
Scala for Java Programmers
Scala for Java ProgrammersScala for Java Programmers
Scala for Java Programmers
 
Taxonomy of Scala
Taxonomy of ScalaTaxonomy of Scala
Taxonomy of Scala
 
RxSwift to Combine
RxSwift to CombineRxSwift to Combine
RxSwift to Combine
 
Java to Scala: Why & How
Java to Scala: Why & HowJava to Scala: Why & How
Java to Scala: Why & How
 
Supercharging reflective libraries with InvokeDynamic
Supercharging reflective libraries with InvokeDynamicSupercharging reflective libraries with InvokeDynamic
Supercharging reflective libraries with InvokeDynamic
 
Scala ntnu
Scala ntnuScala ntnu
Scala ntnu
 
Advance Scala - Oleg Mürk
Advance Scala - Oleg MürkAdvance Scala - Oleg Mürk
Advance Scala - Oleg Mürk
 

Más de Maurice Naftalin

Más de Maurice Naftalin (7)

Lambda/Streams Hands-On Lab
Lambda/Streams Hands-On LabLambda/Streams Hands-On Lab
Lambda/Streams Hands-On Lab
 
What Lies Beneath
What Lies BeneathWhat Lies Beneath
What Lies Beneath
 
Complicating Complexity: Performance in a New Machine Age
Complicating Complexity: Performance in a New Machine AgeComplicating Complexity: Performance in a New Machine Age
Complicating Complexity: Performance in a New Machine Age
 
Shooting the Rapids
Shooting the RapidsShooting the Rapids
Shooting the Rapids
 
Parallel-Ready Java Code: Managing Mutation in an Imperative Language
Parallel-Ready Java Code: Managing Mutation in an Imperative LanguageParallel-Ready Java Code: Managing Mutation in an Imperative Language
Parallel-Ready Java Code: Managing Mutation in an Imperative Language
 
Let's Get to the Rapids
Let's Get to the RapidsLet's Get to the Rapids
Let's Get to the Rapids
 
Shooting the Rapids: Getting the Best from Java 8 Streams
Shooting the Rapids: Getting the Best from Java 8 StreamsShooting the Rapids: Getting the Best from Java 8 Streams
Shooting the Rapids: Getting the Best from Java 8 Streams
 

Último

+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
Health
 
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM TechniquesAI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
VictorSzoltysek
 
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICECHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
9953056974 Low Rate Call Girls In Saket, Delhi NCR
 

Último (20)

call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
 
Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview Questions
 
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
 
Exploring the Best Video Editing App.pdf
Exploring the Best Video Editing App.pdfExploring the Best Video Editing App.pdf
Exploring the Best Video Editing App.pdf
 
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
 
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS LiveVip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
 
Diamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionDiamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with Precision
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTV
 
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
 
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
 
AI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplateAI & Machine Learning Presentation Template
AI & Machine Learning Presentation Template
 
How to Choose the Right Laravel Development Partner in New York City_compress...
How to Choose the Right Laravel Development Partner in New York City_compress...How to Choose the Right Laravel Development Partner in New York City_compress...
How to Choose the Right Laravel Development Partner in New York City_compress...
 
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM TechniquesAI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
 
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
Direct Style Effect Systems -The Print[A] Example- A Comprehension AidDirect Style Effect Systems -The Print[A] Example- A Comprehension Aid
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Models
 
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICECHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
 
How To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.jsHow To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.js
 

Journey's end

  • 1. Journey’s End, JDK.IO, September 2016 Journey’s End Collection and Reduction in the Stream API JavaOne 2016 Maurice Naftalin @mauricenaftalin
  • 2. Journey’s End, JavaOne, September 2016 Maurice Naftalin
  • 3. Journey’s End, JavaOne, September 2016 Maurice Naftalin Java 5
  • 4. Journey’s End, JavaOne, September 2016 Maurice Naftalin Java 5 Java 8
  • 5. Journey’s End, JavaOne, September 2016 Maurice Naftalin Java 5 Java 8
  • 6. Journey’s End, JavaOne, September 2016 Maurice Naftalin Java 5 Java 8 2013
  • 7. Journey’s End, JavaOne, September 2016 Maurice Naftalin Java 5 Java 8 2014
  • 8. Journey’s End, JavaOne, September 2016 Maurice Naftalin Java 5 Java 8 2015
  • 9. Journey’s End, JavaOne, September 2016 • Why collectors? • Using the predefined collectors • Worked problems • Writing your own Journey’s End – Agenda
  • 10. Journey’s End, JavaOne, September 2016 Example Domain city: City name: String age: int Person Person amy = new Person(Athens, "Amy", 21);
 ... List<Person> people = Arrays.asList(jon, amy, bill);

  • 11. Journey’s End, JavaOne, September 2016 Collectors: Journey’s End for a Stream The Life of a Stream Element • Born (at a spliterator) • Transformed (by intermediate operations) • Collected (by a terminal operation)
  • 12. Journey’s End, JavaOne, September 2016 Collectors: Journey’s End for a Stream The Life of a Stream Element • Born (at a spliterator) • Transformed (by intermediate operations) • Collected (by a terminal operation)
  • 13. Journey’s End, JavaOne, September 2016 Collectors: Journey’s End for a Stream The Life of a Stream Element • Born (at a spliterator) • Transformed (by intermediate operations) • Collected (by a terminal operation)
  • 14. Journey’s End, JavaOne, September 2016 Collectors: Journey’s End for a Stream ? The Life of a Stream Element • Born (at a spliterator) • Transformed (by intermediate operations) • Collected (by a terminal operation)
  • 15. Journey’s End, JavaOne, September 2016 Terminal Operations – Search operations – Side-effecting operations – Reductions

  • 16. Journey’s End, JavaOne, September 2016 Search Operations Search operations - • allMatch, anyMatch • findAny, findFirst boolean allAdults = people.stream()
 .allMatch(p -> p.getAge() >= 21);

  • 17. Journey’s End, JavaOne, September 2016 Side-effecting Operations Side-effecting operations • forEach, forEachOrdered
 
 people.stream()
 .forEach(System.out::println); • So could we calculate total ages like this?
 
 int sum = 0;
 people.stream()
 .mapToInt(Person::getAge)
 .forEach(a -> { sum += a }); people.stream()
 .forEach(System.out::println);
 int sum = 0;
 people.stream()
 .mapToInt(Person::getAge)
 .forEach(a -> { sum += a; });

  • 18. Journey’s End, JavaOne, September 2016 Side-effecting Operations Side-effecting operations • forEach, forEachOrdered
 
 people.stream()
 .forEach(System.out::println); • So could we calculate total ages like this?
 
 int sum = 0;
 people.stream()
 .mapToInt(Person::getAge)
 .forEach(a -> { sum += a }); people.stream()
 .forEach(System.out::println);
 int sum = 0;
 people.stream()
 .mapToInt(Person::getAge)
 .forEach(a -> { sum += a; });
 Don’t do this!
  • 19. Journey’s End, JavaOne, September 2016 • Using an accumulator: Reduction – Why? int[] vals = new int[100]; Arrays.setAll(vals, i -> i); int sum = 0; for (int i = 0 ; i < vals.length ; i++) { sum += vals[i]; }

  • 20. Journey’s End, JavaOne, September 2016 • Using an accumulator: Reduction – Why? int[] vals = new int[100]; Arrays.setAll(vals, i -> i); int sum = 0; for (int i = 0 ; i < vals.length ; i++) { sum += vals[i]; }
 0 1 2 3 + + +
  • 21. Journey’s End, JavaOne, September 2016 • Avoiding an accumulator: Reduction – Why?
  • 22. Journey’s End, JavaOne, September 2016 • Avoiding an accumulator: Reduction – Why?
  • 23. Journey’s End, JavaOne, September 2016 • Avoiding an accumulator: Reduction – Why? int[] vals = new int[100]; Arrays.setAll(vals, i -> i); OptionalInt sum = Arrays.stream(vals) .reduce((a,b) -> a + b);
 + + + 1 2 30
  • 24. Journey’s End, JavaOne, September 2016 • Avoiding an accumulator: Reduction – Why? int[] vals = new int[100]; Arrays.setAll(vals, i -> i); OptionalInt sum = Arrays.stream(vals) .reduce((a,b) -> a + b);
 + + + 1 2 30 + + +
  • 25. Journey’s End, JavaOne, September 2016 • Avoiding an accumulator: Reduction – Why? int[] vals = new int[100]; Arrays.setAll(vals, i -> i); OptionalInt sum = Arrays.stream(vals) .reduce((a,b) -> a + b);
 BinaryOperator must be associative! + + + 1 2 30 + + +
  • 26. Journey’s End, JavaOne, September 2016 • Avoiding an accumulator: Reduction – Why? int[] vals = new int[100]; Arrays.setAll(vals, i -> i); OptionalInt sum = Arrays.stream(vals) .reduce((a,b) -> a + b);
 BinaryOperator must be associative! a + (b + c) = (a + b) + c + + + 1 2 30 + + +
  • 27. Journey’s End, JavaOne, September 2016 0 1 2 3 4 5 6 7 + + + + + + + Reduction – Why?
  • 28. Journey’s End, JavaOne, September 2016 0 1 2 3 4 5 6 7 + + + + + + + Reduction – Why?
  • 29. Journey’s End, JavaOne, September 2016 0 1 2 3 4 5 6 7 + + + + + + + Intermediate operations Reduction – Why?
  • 30. Journey’s End, JavaOne, September 2016 Reduction on ImmutableValues Reduction works on immutable values too BigDecimal[] vals = new BigDecimal[100]; Arrays.setAll(vals, i -> new BigDecimal(i)); Optional<BigDecimal> sum = Arrays.stream(vals) .reduce(BigDecimal::add);

  • 31. Journey’s End, JavaOne, September 2016 Reduction to Collections?
  • 32. Journey’s End, JavaOne, September 2016 Reduction to Collections? This also works with collections – sort of ... • for each element, client code creates a new empty collection and adds the single element to it • combines collections using addAll
  • 33. Journey’s End, JavaOne, September 2016 Reduction to Collections? This also works with collections – sort of ... • for each element, client code creates a new empty collection and adds the single element to it • combines collections using addAll We can do better!
  • 34. Journey’s End, JavaOne, September 2016 Reduction over an Identity BigDecimal[] vals = new BigDecimal[100]; Arrays.setAll(vals, i -> new BigDecimal(i)); BigDecimal sum = Arrays.stream(vals) .reduce(BigDecimal.ZERO,BigDecimal::add);

  • 35. Journey’s End, JavaOne, September 2016 Reduction over an Identity BigDecimal[] vals = new BigDecimal[100]; Arrays.setAll(vals, i -> new BigDecimal(i)); BigDecimal sum = Arrays.stream(vals) .reduce(BigDecimal.ZERO,BigDecimal::add);
 Works for immutable objects:
  • 36. Journey’s End, JavaOne, September 2016 Reduction over an Identity + + + 0 1 2 3 + + + 0 4 5 6 7 0 ++ +
  • 37. Journey’s End, JavaOne, September 2016 Reduction to Collections?
  • 38. Journey’s End, JavaOne, September 2016 Reduction to Collections? Reduction over an identity doesn’t work with collections at all • reduction reuses the identity element
  • 39. Journey’s End, JavaOne, September 2016 Reduction to Collections? Reduction over an identity doesn’t work with collections at all • reduction reuses the identity element We’ve got to do better!
  • 40. Journey’s End, JavaOne, September 2016 The Answer – Collectors a a a e0 e1 e2 e3 a a a e4 e5 e6 e7 aa c
  • 41. Journey’s End, JavaOne, September 2016 The Answer – Collectors a a a e0 e1 e2 e3 a a a () -> [] e4 e5 e6 e7 aa c () -> []
  • 42. Journey’s End, JavaOne, September 2016 The Answer – Collectors a a a e0 e1 e2 e3 a a a () -> [] e4 e5 e6 e7 aa c a: accumulator c: combiner () -> []
  • 43. Journey’s End, JavaOne, September 2016 Collectors
  • 44. Journey’s End, JavaOne, September 2016 Collectors So to define a collector, you need to provide • Supplier • Accumulator • Combiner
  • 45. Journey’s End, JavaOne, September 2016 Collectors So to define a collector, you need to provide • Supplier • Accumulator • Combiner That sounds really hard!
  • 46. Journey’s End, JavaOne, September 2016 Collectors So to define a collector, you need to provide • Supplier • Accumulator • Combiner That sounds really hard! Good then that we don’t have to do it … very often
  • 47. Journey’s End, JavaOne, September 2016 • Why collectors? • Using the predefined collectors • Worked problems • Writing your own Journey’s End – Agenda
  • 48. Journey’s End, JavaOne, September 2016 Collectors API Factory methods in the Collectors class.They produce standalone collectors, accumulating to: • framework-supplied containers • custom collections • classification maps
  • 49. Journey’s End, JavaOne, September 2016 Predefined Standalone Collectors – from factory methods in Collectors class • toList(), toSet(), toMap(), joining() • toMap(), toCollection() • groupingBy(), partitioningBy(), groupingByConcurrent() Using the Predefined Collectors
  • 50. Journey’s End, JavaOne, September 2016 Predefined Standalone Collectors – from factory methods in Collectors class • toList(), toSet(), toMap(), joining() • toMap(), toCollection() • groupingBy(), partitioningBy(), groupingByConcurrent() Using the Predefined Collectors framework provides the Supplier
  • 51. Journey’s End, JavaOne, September 2016 Predefined Standalone Collectors – from factory methods in Collectors class • toList(), toSet(), toMap(), joining() • toMap(), toCollection() • groupingBy(), partitioningBy(), groupingByConcurrent() Using the Predefined Collectors user provides the Supplier framework provides the Supplier
  • 52. Journey’s End, JavaOne, September 2016 Predefined Standalone Collectors – from factory methods in Collectors class • toList(), toSet(), toMap(), joining() • toMap(), toCollection() • groupingBy(), partitioningBy(), groupingByConcurrent() Using the Predefined Collectors user provides the Supplier framework provides the Supplier produce a 
 classification map
  • 53. Journey’s End, JavaOne, September 2016 Simple Collector – toSet() Collectors.toSet() people.stream().collect(Collectors.toSet())
  • 54. Journey’s End, JavaOne, September 2016 Simple Collector – toSet() Stream<Person> Collectors.toSet() Set<Person> people.stream().collect(Collectors.toSet()) Collector<Person,?,Set<Person>>
  • 55. Journey’s End, JavaOne, September 2016 Simple Collector – toSet() Stream<Person> Collectors.toSet() Set<Person> people.stream().collect(Collectors.toSet()) bill Collector<Person,?,Set<Person>>
  • 56. Journey’s End, JavaOne, September 2016 Simple Collector – toSet() Stream<Person> Collectors.toSet() Set<Person> people.stream().collect(Collectors.toSet()) bill Collector<Person,?,Set<Person>>
  • 57. Journey’s End, JavaOne, September 2016 Simple Collector – toSet() Stream<Person> Collectors.toSet() Set<Person> people.stream().collect(Collectors.toSet()) bill Collector<Person,?,Set<Person>>
  • 58. Journey’s End, JavaOne, September 2016 Simple Collector – toSet() Stream<Person> Collectors.toSet() Set<Person> people.stream().collect(Collectors.toSet()) bill jon Collector<Person,?,Set<Person>>
  • 59. Journey’s End, JavaOne, September 2016 Simple Collector – toSet() Stream<Person> Collectors.toSet() Set<Person> people.stream().collect(Collectors.toSet()) bill jon Collector<Person,?,Set<Person>>
  • 60. Journey’s End, JavaOne, September 2016 Simple Collector – toSet() Stream<Person> Collectors.toSet() Set<Person> people.stream().collect(Collectors.toSet()) amy bill jon Collector<Person,?,Set<Person>>
  • 61. Journey’s End, JavaOne, September 2016 Simple Collector – toSet() Stream<Person> Collectors.toSet() Set<Person> people.stream().collect(Collectors.toSet()) amy bill jon Collector<Person,?,Set<Person>>
  • 62. Journey’s End, JavaOne, September 2016 Simple Collector – toSet() Collectors.toSet() Set<Person> people.stream().collect(Collectors.toSet()) amy bill jon Collector<Person,?,Set<Person>>
  • 63. Journey’s End, JavaOne, September 2016 Simple Collector – toSet() Collectors.toSet() Set<Person> { , , } people.stream().collect(Collectors.toSet()) amybilljon Collector<Person,?,Set<Person>>
  • 64. Journey’s End, JavaOne, September 2016 toMap(Function<T,K> keyMapper, Function<T,U> valueMapper) people.stream().collect( Collectors.toMap( Person::getCity,
 Person::getName))
  • 65. Journey’s End, JavaOne, September 2016 toMap(Function<T,K> keyMapper, Function<T,U> valueMapper) Stream<Person> toMap() Map<City,String> Collector<Person,?,Map<City,String> people.stream().collect(toMap(Person::getCity,Person::getName))
  • 66. Journey’s End, JavaOne, September 2016 toMap(Function<T,K> keyMapper, Function<T,U> valueMapper) Stream<Person> toMap() Map<City,String> Collector<Person,?,Map<City,String>
  • 67. Journey’s End, JavaOne, September 2016 toMap(Function<T,K> keyMapper, Function<T,U> valueMapper) Stream<Person> toMap() Map<City,String> bill
  • 68. Journey’s End, JavaOne, September 2016 toMap(Function<T,K> keyMapper, Function<T,U> valueMapper) Stream<Person> toMap() Map<City,String> bill Person::getCity
  • 69. Journey’s End, JavaOne, September 2016 toMap(Function<T,K> keyMapper, Function<T,U> valueMapper) Stream<Person> toMap() Map<City,String> London bill
  • 70. Journey’s End, JavaOne, September 2016 toMap(Function<T,K> keyMapper, Function<T,U> valueMapper) Stream<Person> toMap() Map<City,String> London bill Person::getName
  • 71. Journey’s End, JavaOne, September 2016 toMap(Function<T,K> keyMapper, Function<T,U> valueMapper) Stream<Person> toMap() Map<City,String> London “Bill” bill Person::getName
  • 72. Journey’s End, JavaOne, September 2016 toMap(Function<T,K> keyMapper, Function<T,U> valueMapper) Stream<Person> toMap() Map<City,String> London “Bill”
  • 73. Journey’s End, JavaOne, September 2016 toMap(Function<T,K> keyMapper, Function<T,U> valueMapper) Stream<Person> toMap() Map<City,String> amy London “Bill”
  • 74. Journey’s End, JavaOne, September 2016 toMap(Function<T,K> keyMapper, Function<T,U> valueMapper) Stream<Person> toMap() Map<City,String> Athens amy London “Bill”
  • 75. Journey’s End, JavaOne, September 2016 toMap(Function<T,K> keyMapper, Function<T,U> valueMapper) Stream<Person> toMap() Map<City,String> “Amy”Athens London “Bill”
  • 76. Journey’s End, JavaOne, September 2016 toMap(Function<T,K> keyMapper, Function<T,U> valueMapper) Stream<Person> toMap() Map<City,String> “Amy”Athens jon London “Bill”
  • 77. Journey’s End, JavaOne, September 2016 toMap(Function<T,K> keyMapper, Function<T,U> valueMapper) Stream<Person> toMap() Map<City,String> “Amy”Athens London “Bill” Tulsa “Jon”
  • 78. Journey’s End, JavaOne, September 2016 toMap(Function<T,K> keyMapper, Function<T,U> valueMapper) toMap() Map<City,String> “Amy”Athens London “Bill” Tulsa “Jon”
  • 79. Journey’s End, JavaOne, September 2016 toMap(Function<T,K> keyMapper, Function<T,U> valueMapper) toMap() Map<City,String> “Amy”Athens London “Bill” Tulsa “Jon”
  • 80. Journey’s End, JavaOne, September 2016 toMap(Function<T,K> keyMapper, Function<T,U> valueMapper) Stream<Person> toMap() Map<City,String>
  • 81. Journey’s End, JavaOne, September 2016 toMap(Function<T,K> keyMapper, Function<T,U> valueMapper) Stream<Person> toMap() Map<City,String> “Amy”Athens jon London “Bill”
  • 82. Journey’s End, JavaOne, September 2016 toMap(Function<T,K> keyMapper, Function<T,U> valueMapper) Stream<Person> toMap() Map<City,String> “Amy”Athens jon London “Bill” Athens
  • 83. Journey’s End, JavaOne, September 2016 toMap(Function<T,K> keyMapper, Function<T,U> valueMapper) Stream<Person> toMap() Map<City,String> “Amy”Athens jon London IllegalStateException “Bill” Athens
  • 84. Journey’s End, JavaOne, September 2016 toMap(Function<T,K> keyMapper, Function<T,U> valueMapper BinaryOperator<U> mergeFunction) people.stream().collect( Collectors.toMap( Person::getCity,
 Person::getName, (a,b) -> a.concat(b)))
  • 85. Journey’s End, JavaOne, September 2016 toMap(Function<T,K> keyMapper, Function<T,U> valueMapper BinaryOperator<U> mergeFunction) Stream<Person> toMap() Map<City,String>
  • 86. Journey’s End, JavaOne, September 2016 toMap(Function<T,K> keyMapper, Function<T,U> valueMapper BinaryOperator<U> mergeFunction) Stream<Person> toMap() Map<City,String> “Amy”Athens London “Bill” Athens
  • 87. Journey’s End, JavaOne, September 2016 toMap(Function<T,K> keyMapper, Function<T,U> valueMapper BinaryOperator<U> mergeFunction) Stream<Person> toMap() Map<City,String> “Amy”Athens London “Bill” Athens
  • 88. Journey’s End, JavaOne, September 2016 toMap(Function<T,K> keyMapper, Function<T,U> valueMapper BinaryOperator<U> mergeFunction) Stream<Person> toMap() Map<City,String> “Amy”Athens London “Bill” “Jon” Athens
  • 89. Journey’s End, JavaOne, September 2016 toMap(Function<T,K> keyMapper, Function<T,U> valueMapper BinaryOperator<U> mergeFunction) Stream<Person> toMap() Map<City,String> “Amy”Athens London “Bill” “Jon” (a,b) -> a.concat(b) Athens
  • 90. Journey’s End, JavaOne, September 2016 toMap(Function<T,K> keyMapper, Function<T,U> valueMapper BinaryOperator<U> mergeFunction) Stream<Person> toMap() Map<City,String> Athens London “Bill” (a,b) -> a.concat(b) “AmyJon” Athens
  • 91. Journey’s End, JavaOne, September 2016 Collectors API Factory methods in the Collectors class.They produce standalone collectors, accumulating to: • framework-supplied containers • custom collections • classification maps
  • 92. Journey’s End, JavaOne, September 2016 toMap(Function<T,K> keyMapper, Function<T,U> valueMapper BinaryOperator<U> mergeFunction) toMap(Function<T,K> keyMapper, Function<T,U> valueMapper BinaryOperator<U> mergeFunction, Supplier<M> mapFactory) people.stream().collect( Collectors.toMap( Person::getCity,
 Person::getName, (a,b) -> a.concat(b),
 TreeMap::new))
  • 93. Journey’s End, JavaOne, September 2016 toMap(Function<T,K> keyMapper, Function<T,U> valueMapper BinaryOperator<U> mergeFunction, Supplier<M> mapFactory) Stream<Person> toMap() Map<City,String>
  • 94. Journey’s End, JavaOne, September 2016 toMap(Function<T,K> keyMapper, Function<T,U> valueMapper BinaryOperator<U> mergeFunction, Supplier<M> mapFactory) Stream<Person> toMap() Map<City,String>
  • 95. Journey’s End, JavaOne, September 2016 Collecting to Custom Collections
  • 96. Journey’s End, JavaOne, September 2016 Collecting to Custom Collections toCollection(Supplier<C> collectionFactory)
  • 97. Journey’s End, JavaOne, September 2016 Collecting to Custom Collections <C extends Collection<T>> toCollection(Supplier<C> collectionFactory)
  • 98. Journey’s End, JavaOne, September 2016 Collecting to Custom Collections returns Collector<T,?,C> <C extends Collection<T>> toCollection(Supplier<C> collectionFactory)
  • 99. Journey’s End, JavaOne, September 2016 Collecting to Custom Collections returns Collector<T,?,C> <C extends Collection<T>> NavigableSet<String> sortedNames = people.stream() .map(Person::getName)
 .collect(toCollection(TreeSet::new)); toCollection(Supplier<C> collectionFactory)
  • 100. Journey’s End, JavaOne, September 2016 Collectors API Factory methods in the Collectors class.They produce standalone collectors, accumulating to: • framework-supplied containers • custom collections • classification maps
  • 101. Journey’s End, JavaOne, September 2016 Collecting to Classification Maps groupingBy • simple • with downstream • with downstream and map factory partitioningBy
  • 102. Journey’s End, JavaOne, September 2016 groupingBy(Function<T,K> classifier) Uses the classifier function to make a classification mapping Like toMap(), except that the values placed in the map are lists of the elements, one List corresponding to each classification key: For example, use Person.getCity() to make a Map<City,List<Person>> Map<City,List<Person>> peopleByCity = people.stream() .collect(Collectors.groupingBy(Person::getCity));
  • 103. Journey’s End, JavaOne, September 2016 Stream<Person> groupingBy() Map<City,List<Person>> bill jon amy Athens London Collector<Person,?,Map<City,List<Person> groupingBy(Function<Person,City>) Classifier Person→City
  • 104. Journey’s End, JavaOne, September 2016 Stream<Person> groupingBy() Map<City,List<Person>> bill jon amy Athens London groupingBy(Function<Person,City>)
  • 105. Journey’s End, JavaOne, September 2016 Stream<Person> groupingBy() Map<City,List<Person>> bill jon amy Athens bill London groupingBy(Function<Person,City>)
  • 106. Journey’s End, JavaOne, September 2016 Stream<Person> groupingBy() Map<City,List<Person>> bill jon amy Athens billLondon groupingBy(Function<Person,City>) [ ]
  • 107. Journey’s End, JavaOne, September 2016 Stream<Person> groupingBy() Map<City,List<Person>> bill jon amy Athens [ ] bill amy London groupingBy(Function<Person,City>) [ ]
  • 108. Journey’s End, JavaOne, September 2016 Stream<Person> groupingBy() Map<City,List<Person>> bill jon amy Athens [ ] [ , ]bill amy jonLondon groupingBy(Function<Person,City>)
  • 109. Journey’s End, JavaOne, September 2016 groupingBy() Map<City,List<Person>> bill jon amy Athens [ ] [ , ]bill amy jonLondon groupingBy(Function<Person,City>)
  • 110. Journey’s End, JavaOne, September 2016 groupingBy() Map<City,List<Person>> bill jon amy Athens [ ] [ , ]bill amy jonLondon groupingBy(Function<Person,City>)
  • 111. Journey’s End, JavaOne, September 2016 groupingBy(Function<T,K> classifier) Uses the classifier function to make a classification mapping Like toMap(), except that the values placed in the map are lists of the elements, one List corresponding to each classification key: For example, use Person.getCity() to make a Map<City,List<Person>> Map<City,List<Person>> peopleByCity = people.stream() .collect(Collectors.groupingBy(Person::getCity));
  • 112. Journey’s End, JavaOne, September 2016 groupingBy(classifier, downstream) Uses the classifier function to make a classification mapping into a container defined by a downstream Collector Like toMap(), except that the values placed in the map are containers of the elements, one container corresponding to each classification key: For example, use Person.getCity() to make a Map<City,Set<Person>> Map<City,List<Person>> peopleByCity = people.stream() .collect(Collectors.groupingBy(Person::getCity,toSet()));
  • 113. Journey’s End, JavaOne, September 2016 groupingBy(Function classifier,Collector downstream)) Stream<Person> groupingBy() Map<City,Set<Person> bill jon amy London Athens Downstream Collector — toSet() Stream<Person > Classifier Person→City
  • 114. Journey’s End, JavaOne, September 2016 groupingBy(Function classifier,Collector downstream)) Stream<Person> groupingBy() Map<City,Set<Person> bill jon amy London Athens
  • 115. Journey’s End, JavaOne, September 2016 groupingBy(Function classifier,Collector downstream)) Stream<Person> groupingBy() Map<City,Set<Person> bill jon amy London Athens bill
  • 116. Journey’s End, JavaOne, September 2016 groupingBy(Function classifier,Collector downstream)) Stream<Person> groupingBy() Map<City,Set<Person> bill jon amy London Athens bill
  • 117. Journey’s End, JavaOne, September 2016 groupingBy(Function classifier,Collector downstream)) Stream<Person> groupingBy() Map<City,Set<Person> bill jon amy London Athens bill
  • 118. Journey’s End, JavaOne, September 2016 groupingBy(Function classifier,Collector downstream)) Stream<Person> groupingBy() Map<City,Set<Person> bill jon amy London Athensamy bill
  • 119. Journey’s End, JavaOne, September 2016 groupingBy(Function classifier,Collector downstream)) Stream<Person> groupingBy() Map<City,Set<Person> bill jon amy London Athens amy bill
  • 120. Journey’s End, JavaOne, September 2016 groupingBy(Function classifier,Collector downstream)) Stream<Person> groupingBy() Map<City,Set<Person> bill jon amy London Athens amy bill
  • 121. Journey’s End, JavaOne, September 2016 groupingBy(Function classifier,Collector downstream)) Stream<Person> groupingBy() Map<City,Set<Person> bill jon amy London Athens amy jon bill
  • 122. Journey’s End, JavaOne, September 2016 groupingBy(Function classifier,Collector downstream)) Stream<Person> groupingBy() Map<City,Set<Person> bill jon amy London Athens amy jon bill
  • 123. Journey’s End, JavaOne, September 2016 groupingBy(Function classifier,Collector downstream)) groupingBy() Map<City,Set<Person> bill jon amy London Athens amy jon bill
  • 124. Journey’s End, JavaOne, September 2016 groupingBy(Function classifier,Collector downstream)) groupingBy() Map<City,Set<Person> bill jon amy London Athens amy jon bill
  • 125. Journey’s End, JavaOne, September 2016 groupingBy(Function classifier,Collector downstream)) groupingBy() Map<City,Set<Person> bill jon amy London Athens { }amy { , }jonbill
  • 126. Journey’s End, JavaOne, September 2016 groupingBy(Function classifier,Collector downstream)) groupingBy() Map<City,Set<Person> bill jon amy London Athens { }amy { , }jonbill
  • 127. Journey’s End, JavaOne, September 2016 mapping(Function mapper,Collector downstream)) Applies a mapping function to each input element before passing it to the downstream collector.
  • 128. Journey’s End, JavaOne, September 2016 mapping(Function mapper,Collector downstream)) Applies a mapping function to each input element before passing it to the downstream collector. Set<City> inhabited = people.stream()
 .collect(mapping(Person::getCity,toSet())); Animation example
  • 129. Journey’s End, JavaOne, September 2016 mapping(Function mapper,Collector downstream)) LondonStream<Person> mapping() bill jon amy Athens Mapper Person→City Downstream Collector — toSet() Stream<City> Set<City>
  • 130. Journey’s End, JavaOne, September 2016 mapping(Function mapper,Collector downstream)) LondonStream<Person> mapping() bill jon amy Athens Set<City>
  • 131. Journey’s End, JavaOne, September 2016 mapping(Function mapper,Collector downstream)) LondonStream<Person> mapping() bill jon amy Athens London Set<City>
  • 132. Journey’s End, JavaOne, September 2016 mapping(Function mapper,Collector downstream)) LondonStream<Person> mapping() bill jon amy Athens Athens London Set<City>
  • 133. Journey’s End, JavaOne, September 2016 mapping(Function mapper,Collector downstream)) LondonStream<Person> mapping() bill jon amy Athens Athens LondonLondon Set<City>
  • 134. Journey’s End, JavaOne, September 2016 mapping(Function mapper,Collector downstream)) London mapping() bill jon amy Athens Athens LondonLondon Set<City>
  • 135. Journey’s End, JavaOne, September 2016 mapping(Function mapper,Collector downstream)) London mapping() bill jon amy { , } Athens Athens London Set<City>
  • 136. Journey’s End, JavaOne, September 2016 mapping(Function mapper,Collector downstream)) London mapping() bill jon amy { , } Athens Athens London Set<City>
  • 137. Journey’s End, JavaOne, September 2016 mapping(Function mapper,Collector downstream)) Applies a mapping function to each input element before passing it to the downstream collector. Set<City> inhabited = people.stream()
 .collect(mapping(Person::getCity,toSet())); Animation example
  • 138. Journey’s End, JavaOne, September 2016 mapping(Function mapper,Collector downstream)) Applies a mapping function to each input element before passing it to the downstream collector. Set<City> inhabited = people.stream()
 .collect(mapping(Person::getCity,toSet())); Map<City,String> namesByCity = people.stream()
 .collect(groupingBy(Person::getCity, mapping(Person::getName,joining())); Animation example Sensible example
  • 139. Collectors’ Fair, JavaOne, October 2016 groupingBy() bill jon amy Athens billamyjon London Collector<Person,?,String> Classifier Person→City JDK Collectors with Java 8 Streams mapping() Mapper Person→String Stream<String> joining() Collector<CharSequence,?,String>
  • 140. Journey’s End, JavaOne, September 2016 Dualling Convenience Reductions Terminal operation Collectors factory method count() counting() max() min() maxBy() minBy() sum() average() summingXxx() averagingXxx() summaryStatistics() summarizingXxx() reduce(accumulator) reduce(identity, accumulator) reduce(identity, accumulator, combiner) reducing(accumulator) reducing(identity, accumulator) reducing(identity, accumulator, combiner)
  • 141. Journey’s End, JavaOne, September 2016 Concurrent Collection
  • 142. Journey’s End, JavaOne, September 2016 Concurrent Collection
  • 143. Journey’s End, JavaOne, September 2016 Thread safety is guaranteed by the framework • Even for non-threadsafe containers! Concurrent Collection
  • 144. Journey’s End, JavaOne, September 2016 Thread safety is guaranteed by the framework • Even for non-threadsafe containers! But at a price... So what if your container is already threadsafe? • A concurrentMap implementation, for example? Concurrent Collection
  • 145. Journey’s End, JavaOne, September 2016 Thread safety is guaranteed by the framework • Even for non-threadsafe containers! But at a price... So what if your container is already threadsafe? • A concurrentMap implementation, for example? Concurrent Collection
  • 146. Journey’s End, JavaOne, September 2016 Thread safety is guaranteed by the framework • Even for non-threadsafe containers! But at a price... So what if your container is already threadsafe? • A concurrentMap implementation, for example? Every overload of toMap() and groupingBy() has a dual • toConcurrentMap(...) • groupingByConcurrent(...) Concurrent Collection
  • 147. Journey’s End, JavaOne, September 2016 • Why collectors? • Using the predefined collectors • Worked problems • Writing your own Journey’s End – Agenda
  • 149. Most Popular Age Optional<Integer> modalAge = populationByAge
  • 150. Most Popular Age Optional<Integer> modalAge = populationByAge .entrySet()
  • 151. Most Popular Age Optional<Integer> modalAge = populationByAge .entrySet() .stream()
  • 152. Most Popular Age Optional<Integer> modalAge = populationByAge .entrySet() .stream() .sorted(Entry.<Integer,Long>comparingByValue().reversed())
  • 153. Most Popular Age Optional<Integer> modalAge = populationByAge .entrySet() .stream() .sorted(Entry.<Integer,Long>comparingByValue().reversed()) .map(Entry::getKey)
  • 154. Most Popular Age Optional<Integer> modalAge = populationByAge .entrySet() .stream() .sorted(Entry.<Integer,Long>comparingByValue().reversed()) .map(Entry::getKey) .findFirst();
  • 156. Most Popular Age Optional<Integer> modalAge = populationByAge
  • 157. Most Popular Age Optional<Integer> modalAge = populationByAge .entrySet()
  • 158. Most Popular Age Optional<Integer> modalAge = populationByAge .entrySet() .stream()
  • 159. Most Popular Age Optional<Integer> modalAge = populationByAge .entrySet() .stream() .collect(maxBy(Comparator.comparing(Map.Entry::getValue)))
  • 160. Most Popular Age Optional<Integer> modalAge = populationByAge .entrySet() .stream() .collect(maxBy(Comparator.comparing(Map.Entry::getValue))) .map(Map.Entry::getKey);
  • 161. Most Popular Age Optional<Integer> modalAge = populationByAge .entrySet() .stream() .collect(maxBy(Comparator.comparing(Map.Entry::getValue))) .map(Map.Entry::getKey);
  • 162. Map<Long, Set<Integer>> collect = people.stream() .collect(groupingBy(People::getAge, counting())) .entrySet() .stream() .collect(groupingBy(Entry::getValue, mapping(Entry::getKey, toSet()))); Most Popular Ages
  • 163. Journey’s End, JavaOne, September 2016 • Why collectors? • Using the predefined collectors • Worked problems • Writing your own Journey’s End – Agenda
  • 164. Journey’s End, JavaOne, September 2016 Writing a Collector
  • 165. Journey’s End, JavaOne, September 2016 Writing a Collector Why would you want to?
  • 166. Journey’s End, JavaOne, September 2016 Writing a Collector Why would you want to? • accumulate to a container that doesn’t implement Collection
  • 167. Journey’s End, JavaOne, September 2016 Writing a Collector Why would you want to? • accumulate to a container that doesn’t implement Collection • share state between values being collected
  • 168. Journey’s End, JavaOne, September 2016 Oprah’s Problem
  • 169. Journey’s End, JavaOne, September 2016 Oprah’s Problem How to find a book?
  • 170. Journey’s End, JavaOne, September 2016 Oprah’s Problem How to find a book? 336 640 144 624 Page count 239 640 384 1104 172 400
  • 171. Journey’s End, JavaOne, September 2016 What Oprah Needs New Earth 0 Poisonwood Bible 336 Night 976 A Fine Balance 1120 ... Cumulative page counts
  • 172. Journey’s End, JavaOne, September 2016 Supplier and Accumulator “NE” 336 0 “PB” 640 336[ ], ]“NE” 336 0[ ][ aNewEarth thePoisonwoodBible accumulator accumulator
  • 173. Journey’s End, JavaOne, September 2016 Combiner ,“Night” 144 976 “AFB” 624 1120 ]“NE” 336 0 “PB” 640 336[ , ,
  • 174. Journey’s End, JavaOne, September 2016 Combiner ,“Night” 144 0[ “AFB” 624 144 ]“NE” 336 0 “PB” 640 336[ ], ,“Night” 144 976 “AFB” 624 1120 ]“NE” 336 0 “PB” 640 336[ , ,
  • 175. Journey’s End, JavaOne, September 2016 Combiner combiner ,“Night” 144 0[ “AFB” 624 144 ]“NE” 336 0 “PB” 640 336[ ], ,“Night” 144 976 “AFB” 624 1120 ]“NE” 336 0 “PB” 640 336[ , ,
  • 176. Journey’s End, JavaOne, September 2016 Combiner combiner ,“Night” 144 0[ “AFB” 624 144 ]“NE” 336 0 “PB” 640 336[ ], ,“Night” 144 976 “AFB” 624 1120 ]“NE” 336 0 “PB” 640 336[ , , 976
  • 177. Journey’s End, JavaOne, September 2016 Combiner combiner ,“Night” 144 0[ “AFB” 624 144 ]“NE” 336 0 “PB” 640 336[ ], ,“Night” 144 976 “AFB” 624 1120 ]“NE” 336 0 “PB” 640 336[ , , 976
  • 178. Journey’s End, JavaOne, September 2016 Combiner combiner ,“Night” 144 0[ “AFB” 624 144 ]“NE” 336 0 “PB” 640 336[ ], ,“Night” 144 976 “AFB” 624 1120 ]“NE” 336 0 “PB” 640 336[ , ,
  • 179. Journey’s End, JavaOne, September 2016 Using Reduction Instead... “New Earth” 336 0 “Poisonwood Bible” 640 336[ , “Night” 144 976, ] newEarth poisonwood night
  • 180. Journey’s End, JavaOne, September 2016 Using Reduction Instead... “New Earth” 336 0 “Poisonwood Bible” 640 336[ , “Night” 144 976, ] newEarth poisonwood night Page count Start displacement
  • 181. Journey’s End, JavaOne, September 2016 Using Reduction Instead... “New Earth” 336 0 “Poisonwood Bible” 640 336[ , “Night” 144 976, ] ]“New Earth” 336 0 “Poisonwood Bible” 640 0[ ] ]“Night” 144 0 ][[ newEarth poisonwood night
  • 182. Journey’s End, JavaOne, September 2016 Using Reduction Instead... “New Earth” 336 0 “Poisonwood Bible” 640 336[ , “Night” 144 976, ] ]“New Earth” 336 0 “Poisonwood Bible” 640 0[ ] ]“Night” 144 0 ][[ newEarth poisonwood night Map
  • 183. Journey’s End, JavaOne, September 2016 Using Reduction Instead... “New Earth” 336 0 “Poisonwood Bible” 640 336[ , “Night” 144 976, ] ]“New Earth” 336 0 “Poisonwood Bible” 640 0[ ] ]“Night” 144 0 ][[ newEarth poisonwood night Reduce Map
  • 184. Journey’s End, JavaOne, September 2016 Using Reduction Instead... “New Earth” 336 0 “Poisonwood Bible” 640 336[ , “Night” 144 976, ] ]“New Earth” 336 0 “Poisonwood Bible” 640 0[ ] ]“Night” 144 0 ][[ PartialResult::new ArrayDeque::new newEarth poisonwood night Reduce Map
  • 185. Journey’s End, JavaOne, September 2016 Using Reduction Instead... “New Earth” 336 0 “Poisonwood Bible” 640 336[ , “Night” 144 976, ] ]“New Earth” 336 0 “Poisonwood Bible” 640 0[ ] ]“Night” 144 0 ][[ PartialResult::new ArrayDeque::new PartialResult::new ArrayDeque::new PartialResult::new ArrayDeque::new newEarth poisonwood night Reduce
  • 186. Journey’s End, JavaOne, September 2016 Performance of Collectors Depends on the performance of accumulator and combiner functions • toList(), toSet(), toCollection – performance will probably be dominated by accumulator, but remember that the framework will need to manage multithread access to non-threadsafe containers for the combine operation toMap(), toConcurrentMap() • map merging is slow. Resizing maps, especially concurrent maps, is particularly expensive.Whenever possible, presize all data structures, maps in particular.
  • 187. Journey’s End, JavaOne, September 2016 Conclusion Collectors • generalisation of reduction • allow a functional style while continuing to work with a language based on mutation • designed for composition • flexible and powerful programming tool • take a bit of getting used to! – but they’re worth it!
  • 188. Journey’s End, JavaOne, September 2016 Questions?
  • 189. Journey’s End, JavaOne, September 2016 Questions?