Terminal operation either returns one value (of the same or another type than the input type) or does not return anything at all (produces only side effects). It does not allow another operation to be applied afterward and closes the stream.
In this post, we will continue covering the last of the terminal operations called collect():
R collect(Collector<T,A,R> collector)
It is a specialization of the reduce() operation. It allows implementing a vast variety of algorithms using the ready-to-use collectors from the java.util.stream.Collectors class. We discussed how to create a custom collector in Java streams 25. Collect 1. Custom collector. In this article, we will use only the collectors produced by the Collectors class.
Creating Map object using Collectors.groupingByConcurrent() collector
The Collectors.groupingByConcurrent() collector produces essentially the same result as the Collectors.groupingBy() collector (see Java streams 33. Collect 9. Collectors.groupingBy() collector) except that the resulting Map is unordered and optimized for parallel stream processing.
There are several overloaded versions of factory methods that create the Collectors.c() collector (very similar to the Collectors.groupingBy() factories):
— Collector<T,?,Map<K,List<T>>> groupingByConcurrent(Function<T,K> classifier) – returns a Collector implementing a “group by” operation on input elements of type T, grouping elements according to a classification function, and returning the results in a Map;
— Collector<T,?,Map<K,D>> groupingByConcurrent(Function<T,K> classifier, Collector<T,A,D> downstream) – returns a Collector implementing a cascaded “group by” operation on input elements of type T, grouping elements according to a classification function, and then performing a reduction operation on the values associated with a given key using the specified downstream Collector;
— Collector<T,?,M> groupingByConcurrent(Function<T,K> classifier, Supplier<M> mapSupplier, Collector<T,A,D> downstream) – returns a Collector implementing a cascaded “group by” operation on input elements of type T, grouping elements according to a classification function, and then performing a reduction operation on the values associated with a given key using the specified downstream Collector.
The classifier function extracts from the element the value that is going to serve as a key in the resulting Map. This key is mapped to the value (List, by default, but can be any other object created by downstream function) that contains stream elements that yielded the same key.
The downstream is a collector that creates an object (mapped to the key produced by the classifier) where all elements that yielded the same key value are stored.
The mapSupplier is used when a specific implementation of Map interface is required. It is called only once (whether the stream is parallel or not), while the collector produced by Collectors.groupingBy() calls the corresponding supplier many times).
The following are the examples of the Collectors.groupingByConcurrent() usage:
ConcurrentMap<String, List<String>> map1 =
Stream.of("cat", "fish", "cat", "dog")
.collect(Collectors.
groupingByConcurrent(Function.identity()));
System.out.print(map1);
//prints: {fish=[fish], cat=[cat, cat], dog=[dog]}
ConcurrentMap<Integer, List<String>> map2 =
Stream.of("cat", "fish", "cat", "dog")
.collect(Collectors.
groupingByConcurrent(String::length));
System.out.print(map2);
//prints: {3=[cat, cat, dog], 4=[fish]}
ConcurrentMap<Integer, Set<String>> map3 =
Stream.of("cat", "fish", "cat", "dog")
.collect(Collectors.
groupingByConcurrent(String::length,
Collectors.toSet()));
System.out.print(map3);
//prints: {3=[cat, dog], 4=[fish]}
ConcurrentMap<String, Long> map4 =
Stream.of("cat", "fish", "cat", "dog")
.collect(Collectors.
groupingByConcurrent(Function.identity(),
Collectors.counting()));
System.out.print(map4);
//prints: {fish=1, cat=2, dog=1}
ConcurrentMap<Integer, Map<String, List<String>>> map5 =
Stream.of("cat", "fish", "cat", "dog")
.collect(Collectors.
groupingByConcurrent(String::length,
Collectors.groupingBy(Function.identity())));
System.out.print(map5);
//prints: {3={cat=[cat, cat], dog=[dog]}, 4={fish=[fish]}}
ConcurrentMap<Integer, Map<String, Long>> map6 =
Stream.of("cat", "fish", "cat", "dog")
.collect(Collectors.
groupingByConcurrent(String::length,
Collectors.groupingBy(Function.identity(),
Collectors.counting())));
System.out.print(map6);
//prints: {3={cat=2, dog=1}, 4={fish=1}}
ConcurrentSkipListMap<Integer, Map<String, Long>> map7 =
Stream.of("cat", "fish", "cat", "dog")
.collect(Collectors.
groupingByConcurrent(String::length,
ConcurrentSkipListMap::new,
Collectors.groupingBy(Function.identity(),
Collectors.counting())));
System.out.print(map7);
//prints: {3={cat=2, dog=1}, 4={fish=1}}
In the next post, we will talk about creating a Map object using Collectors.partitioningBy() collector.
See other posts on Java 8 streams and posts on other topics.
You can also use navigation pages for Java stream related blogs:
— Java 8 streams blog titles
— Create stream
— Stream operations
— Stream operation collect()
The source code of all the code examples is here in GitHub.
Send your comments using the link Contact or in response to my newsletter.
If you do not receive the newsletter, subscribe via link Subscribe under Contact.