并行流

时间:2018-04-05 11:40:13

标签: concurrency java-8 java-stream

有一个并行计算最常用名称(Human[] people的函数。但是有数据竞争。为什么呢?

    Map<String, Integer> nameMap = new ConcurrentHashMap<>();
        Arrays.stream(people)
                .parallel()
                .filter(p -> p.isAdult())
                .map(Human::getName)
                .forEach(p -> nameMap.put(p, nameMap.containsKey(p) ? nameMap.get(p) + 1 : 1));
        return nameMap.entrySet().parallelStream().max((entry1, entry2) -> entry1.getValue() > entry2.getValue() ? 1 : -1).get().getKey();

1 个答案:

答案 0 :(得分:3)

因为您正在执行get,然后增加然后 put;在某人之间可能已经将该条目放入nameMap

您可以在这里使用原子ConcurrentHashMap#merge,或者更好地使用Collectors.toConcurrentMap

修改

你本可以做得更清楚一点:

  Arrays.stream(people)
        .parallel()
        .filter(Human::isAdult)
        .collect(Collectors.groupingBy(Human::getName, Collectors.counting()))
        .entrySet()
        .stream()
        .max(Comparator.comparing(Entry::getValue))
        .map(Entry::getKey)
        .get();

请注意,我已经接近确定您根本不需要parallel