Java streams 32. Collect 8. Collectors.toConcurrentMap() collector

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.toConcurrentMap() collector

The Collectors.toConcurrentMap() collector produces essentially the same result as the Collectors.toMap() collector (see Java streams 31. Collect 7. Collectors.toMap() 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.toConcurrentMap() collector (very similar to the Collectors.toMap() factories):

Collector<T,?,Map<K,U>> toConcurrentMap(Function<T,K> keyMapper, Function<T,U> valueMapper) – returns a Collector that accumulates elements into a Map whose keys and values are the result of applying the provided mapping functions to the input elements;

Collector<T,?,Map<K,U>> toConcurrentMap(Function<T,K> keyMapper, Function<T,U> valueMapper, BinaryOperator<U> mergeFunction) – returns a Collector that accumulates elements into a Map whose keys and values are the result of applying the provided mapping functions to the input elements;

Collector<T,?,M> toConcurrentMap(Function<T,K> keyMapper, Function<T,U> valueMapper, BinaryOperator<U> mergeFunction, Supplier<M> mapSupplier) – returns a Collector that accumulates elements into a Map whose keys and values are the result of applying the provided mapping functions to the input elements.

The keyMapper function extracts from the element the value that is going to serve as a key in the resulting Map. The valueMapper is the function that extracts value from the stream element that is going to be used as a value mapped to the key.

The mergeFunction is used when two values are matched to the same key, so it combines such values to resolve the clash.

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.toMap() calls the corresponding supplier many times). 

The following are the examples of the Collectors.toConcurrentMap() usage:

     
  ConcurrentMap<String, Integer> map1 = 
                       Stream.of("cat", "fish", "dog")
      .parallel()
      .collect(Collectors
          .toConcurrentMap(Function.identity(), 
                                      String::length));
  System.out.print(map1); //prints: {fish=4, cat=3, dog=3}

  try {
    ConcurrentMap<String, Integer> map2 = 
                         Stream.of("cat", "fish", "cat")
        .parallel()
        .collect(Collectors
            .toConcurrentMap(Function.identity(),          
                                      String::length));
  } catch (Exception ex){
    System.out.print(ex.getMessage()); 
      //prints: Duplicate key cat (attempted merging values 3 and 3)
  }

  //First key wins
  ConcurrentMap<String, Integer> map3 = 
                      Stream.of("cat", "fish", "cat")
      .parallel()
      .collect(Collectors
          .toConcurrentMap(Function.identity(), 
                            String::length, 
                             (oldValue, nextValue) -> oldValue));
  System.out.print(map3);        //prints: {fish=4, cat=3}

  //Combines the values
  ConcurrentMap<String, Integer> map4 = 
                      Stream.of("cat", "fish", "cat")
      .parallel()
      .collect(Collectors
           .toConcurrentMap(Function.identity(), 
                             String::length, 
                              (oldValue, nextValue) -> oldValue + 100));
  System.out.print(map4);        //prints: {fish=4, cat=103}

  ConcurrentSkipListMap<String, Integer> map6 = 
                      Stream.of("cat", "fish", "cat", "cat")
      .parallel()
      .collect(Collectors
           .toConcurrentMap(Function.identity(), 
                             String::length, 
                              (oldValue, nextValue) -> oldValue + 100, 
                               ConcurrentSkipListMap::new));
  System.out.print(map6);        //prints: {cat=203, fish=4}

In the next post, we will talk about creating a Map object using Collectors.groupingBy() 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.

Powered by WordPress. Designed by Woo Themes