繁体   English   中英

在Java中使用并行流但未获得期望值

[英]Using parallel stream in Java but not getting the expected value

我有一个关于字数统计的代码段:

    String[] wordCountArr = {"a", "b", "c", "a", "a", "b", "c", "d", "e"};
    Stream.of(wordCountArr).collect(TreeMap::new,
            (treeMap, str) -> {

                Object countValue = treeMap.get(str);
                if (countValue != null) {
                    Integer count = Integer.valueOf(countValue.toString());
                    treeMap.put(str, count + 1);
                }
                else {
                    treeMap.put(str, 1);
                }
            }, (treeMap, treeMap2) -> {
                treeMap.putAll(treeMap2);
            }).entrySet()
          .forEach(System.out::println);

它得到期望值:a = 3 b = 2 c = 2 d = 1 e = 1,但是collect函数的Combiner似乎没有执行。 然后我得到了: Java 8 Stream-Reduce函数的组合器未执行 ,并将代码更改为:

    Stream.of(wordCountArr).parallel().collect(TreeMap::new,
            (treeMap, str) -> {

                Object countValue = treeMap.get(str);
                if (countValue != null) {
                    Integer count = Integer.valueOf(countValue.toString());
                    treeMap.put(str, count + 1);
                }
                else {
                    treeMap.put(str, 1);
                }
            }, (treeMap, treeMap2) -> {
                treeMap.putAll(treeMap2);
            }).entrySet()
          .forEach(System.out::println);

但结果并非预期:a = 1 b = 1 c = 1 d = 1 e = 1,我想也许putAll函数只是替换了旧的映射。 有什么好主意可以得出正确的结果吗? 使用并行流是否更有效? 谢谢!

解决了:

合并两个映射的最佳实践是什么?

仅当使用并行流时框架尝试加入多个fork的结果时,才执行组合器。

因此,在第一个版本中,合并器不会执行。

您的第二个版本的代码可能会导致ConcurrentModificationException,因为使用并行流时TreeMap不是线程安全的。

还有一点是,当您合并两棵树时,您忘记了对两棵树的值求和。 您将treeMap所有内容与treeMap合并,因此treeMap2的当前值treeMap被丢弃: treeMap.putAll(treeMap2);

您必须手动遍历treeMap键,将值与treeMap2相加, treeMap2

我不知道您为什么要使用这种方法,但是要计算每个组的项目,您可以简单地使用groupingBy

Map<String, Long> countMap = Stream.of(wordCountArr).collect(Collectors.groupingBy(Function.identity(), 
           Collectors.counting()));
String[] wordCountArr = {"a", "b", "c", "a", "a", "b", "c", "d", "e"};
Map<String, Long> countMap = Stream.of(wordCountArr).collect(Collectors.groupingBy(letter -> letter, Collectors.counting()));
countMap.forEach((s, count) -> System.out.println(s + " : " + count));

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM