我想通过Java 8 Stream
和Collector
接口将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
,如果您使用并行流。