Counting
The collector created by the Collectors.counting() method performs a functional reduction to count the input elements.
static <T> Collector<T,?,Long> counting()
The collector returned counts the number of input elements of type T. If there are no elements, the result is Long.valueOf(0L). Note that the result is of type Long.
The wildcard ? represents any type, and in the method declaration, it is the type parameter for the mutable type that is accumulated by the reduction operation.
In the stream pipeline at (1), the collector Collectors.counting() is used in a standalone capacity to count the number of jazz music CDs.
Long numOfJazzCds1 = CD.cdList.stream().filter(CD::isJazz)
.collect(Collectors.counting()); // (1) Standalone collector
System.out.println(numOfJazzCds1); // 3
In the stream pipeline at (2), the collector Collectors.counting() is used as a downstream collector in a grouping operation that groups the CDs by musical genre and uses the downstream collector to count the number of CDs in each group.
Map<Genre, Long> grpByGenre = CD.cdList.stream()
.collect(Collectors.groupingBy(
CD::genre,
Collectors.counting())); // (2) Downstream collector
System.out.println(grpByGenre); // {POP=2, JAZZ=3}
System.out.println(grpByGenre.get(Genre.JAZZ)); // 3
The collector Collectors.counting() performs effectively the same functional reduction as the Stream.count() terminal operation (p. 953) at (3).
long numOfJazzCds2 = CD.cdList.stream().filter(CD::isJazz)
.count(); // (3) Stream.count()
System.out.println(numOfJazzCds2); // 3
Finding Min/Max
The collectors created by the Collectors.maxBy() and Collectors.minBy() methods perform a functional reduction to find the maximum and minimum elements in the input elements, respectively. As there might not be any input elements, an Optional<T> is returned as the result.
static <T> Collector<T,?,Optional<T>> maxBy(Comparator<? super T> cmp)
static <T> Collector<T,?,Optional<T>> minBy(Comparator<? super T> cmp)
Return a collector that produces an Optional<T> with the maximum or minimum element of type T according to the specified Comparator, respectively.
The natural order comparator for CDs defined at (1) is used in the stream pipelines below to find the maximum CD. The collector Collectors.maxBy() is used as a standalone collector at (2), using the natural order comparator to find the maximum CD. The Optional<CD> result can be queried for the value.
Comparator<CD> natCmp = Comparator.naturalOrder(); // (1)
Optional<CD> maxCD = CD.cdList.stream()
.collect(Collectors.maxBy(natCmp)); // (2) Standalone collector
System.out.println(“Max CD: “
+ maxCD.map(CD::title).orElse(“No CD.”)); // Max CD: Java Jive
In the pipeline below, the CDs are grouped by musical genre, and the CDs in each group are reduced to the maximum CD by the downstream collector Collectors.maxBy() at (3). Again, the downstream collector uses the natural order comparator, and the Optional<CD> result in each group can be queried.
// Group CDs by musical genre, and max CD in each group.
Map<Genre, Optional<CD>> grpByGenre = CD.cdList.stream()
.collect(Collectors.groupingBy(
CD::genre,
Collectors.maxBy(natCmp))); // (3) Downstream collector
System.out.println(grpByGenre);
//{JAZZ=Optional[<Jaav, “Java Jam”, 6, 2017, JAZZ>],
// POP=Optional[<Jaav, “Java Jive”, 8, 2017, POP>]}
System.out.println(“Title of max Jazz CD: “
+ grpByGenre.get(Genre.JAZZ)
.map(CD::title)
.orElse(“No CD.”)); // Title of max Jazz CD: Java Jam
The collectors created by the Collectors.maxBy() and Collectors.minBy() methods are effectively equivalent to the max() and min() terminal operations provided by the stream interfaces (p. 954), respectively. In the pipeline below, the max() terminal operation reduces the stream of CDs to the maximum CD at (4) using the natural order comparator, and the Optional<CD> result can be queried.
Optional<CD> maxCD1 = CD.cdList.stream()
.max(natCmp); // (4) max() on Stream<CD>.
System.out.println(“Title of max CD: “
+ maxCD1.map(CD::title)
.orElse(“No CD.”)); // Title of max CD: Java Jive