Collectors.toConcurrentMap和通过Collectors.toMap供应商选项将Map转换为ConcurrentHashMap有什么区别?

时间:2016-11-30 12:21:43

标签: java java-8 java-stream concurrenthashmap collectors

我想通过Java 8 MapConcurrentHashMap界面将Stream转换为Collector,我可以使用两个选项。

第一个:

Map<Integer, String> mb = persons.stream()
                                 .collect(Collectors.toMap(
                                            p -> p.age, 
                                            p -> p.name, 
                                            (name1, name2) -> name1+";"+name2,
                                            ConcurrentHashMap::new));

第二个:

Map<Integer, String> mb1 = persons.stream()
                                  .collect(Collectors.toConcurrentMap(
                                             p -> p.age, 
                                             p -> p.name));

哪一个是更好的选择?我什么时候应该使用每个选项?

2 个答案:

答案 0 :(得分:9)

处理并行流时,它们之间存在差异。

toMap - &gt;是非并发收集器

toConcurrentMap - &gt;是一个并发收集器(这可以从他们的特征中看出来。)

区别在于 toMap 会创建多个中间结果然后合并在一起(这样的收集器的供应商将被多次调用),而 toConcurrentMap 将创建一个单个结果,每个Thread都会向它抛出结果(这样一个收集器的供应商只会被调用一次)

为什么这很重要?这涉及插入顺序(如果重要)。

toMap 将通过合并多个中间结果在遭遇顺序中在结果Map中插入值(该收集器的供应商被多次调用以及组合器)

toConcurrentMap 将通过将所有元素抛出到公共结果容器(在本例中为ConcurrentHashMap)以任何顺序(未定义)收集元素。供应商只召集一次,Accumulator多次召唤,而Combiner永远不召唤。

这里的一个小警告是,CONCURRENT收集器不能调用合并:要么流必须有UNORDERED标志 - 要么通过unordered()显式调用,要么流的源不是有序的(例如Set)。

答案 1 :(得分:5)

来自toMap&#39; Javadoc:

  

返回的收集器不是并发的。对于并行流管道,组合器功能通过将键从一个映射合并到另一个映射来操作,这可能是昂贵的操作。如果不需要将结果以遭遇顺序插​​入到Map中,则使用toConcurrentMap(Function,Function)可以提供更好的并行性能。

toConcurrentMap不会在遇到顺序的情况下将结果插入到地图中,但应该会提供更好的效果。

如果您不关心广告订单,建议您在使用并行广告时使用toConcurrentMap