collector.toconcurrentmap和通过collectors.tomap供应商选项将映射转换为concu



我想通过Java 8 StreamCollector接口将Map转换为ConcurrentHashMap,我可以使用两个选项。

第一个:

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));

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

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

toMap->是一个非电流收集器

toConcurrentMap->是一个并发收集器(可以从其特征中看到)。

区别在于, tomap 将创建多个中间结果,然后将合并然后一起(该收集器的供应商将被称为多次),而 toconcurrentmap 将创建一个结果,每个线程都会向其投掷结果(此类收集器的供应商只会被调用一次)

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

tomap 通过合并多个中间结果(该收集器的供应商和组合仪)将在遇到顺序中插入值的映射中的值)

toConcurrentMap 将通过将所有元素扔在一个共同的结果容器上(在这种情况下为ConsurrentHashMap),以任何顺序(未定义)收集元素。供应商仅被称为一次,累加器多次,而组合者永远不会。

这里的小警告是,要使CONCURRENT收集器不调用合并:要么流必须具有UNORDERED标志 - 要么通过unordered()显式调用,要么在未订购流的源时(例如,Set))。

来自 toMap的javadoc:

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

toConcurrentMap在相遇顺序中不会将结果插入地图,但应该提供更好的性能。

如果您不在乎插入顺序,则建议使用toConcurrentMap,如果您使用并行流。

最新更新