Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/jsf/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Java中使用并行流,但未获得预期值_Java - Fatal编程技术网

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

在Java中使用并行流,但未获得预期值,java,Java,我有一个关于单词计数的代码片段: 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

我有一个关于单词计数的代码片段:

    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=3b=2c=2d=1e=1,但collect函数的组合器似乎没有执行。然后我得到了这个:并将代码更改为:

    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=1b=1c=1d=1e=1,我想可能putAll函数只是替换了旧的映射。有什么好主意可以得到正确的结果吗?使用并行流是否更有效?谢谢

已解决:


将putAll替换为merge

当您使用并行流时,仅当框架尝试连接多个fork的结果时,才会执行合并器

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

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

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

您必须手动迭代
treeMap
中的键,将值与
treeMap2
相加并返回

我不知道您为什么会提出这种方法,但要计算每组的商品数量,您只需使用
groupingBy

Map<String, Long> countMap = Stream.of(wordCountArr).collect(Collectors.groupingBy(Function.identity(), 
           Collectors.counting()));
Map countMap=Stream.of(wordCountArr).collect(collector.groupingBy(Function.identity()),
收集器。计数();

当您使用并行流时,只有当框架尝试连接多个fork的结果时,组合器才会执行

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

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

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

您必须手动迭代
treeMap
中的键,将值与
treeMap2
相加并返回

我不知道您为什么会提出这种方法,但要计算每组的商品数量,您只需使用
groupingBy

Map<String, Long> countMap = Stream.of(wordCountArr).collect(Collectors.groupingBy(Function.identity(), 
           Collectors.counting()));
Map countMap=Stream.of(wordCountArr).collect(collector.groupingBy(Function.identity()),
收集器。计数();
String[]wordCountArr={“a”、“b”、“c”、“a”、“a”、“b”、“c”、“d”、“e”};
Map countMap=Stream.of(wordCountArr).collect(Collectors.groupby(letter->letter,Collectors.counting());
countMap.forEach((s,count)->System.out.println(s+“:”+count));
String[]wordCountArr={“a”、“b”、“c”、“a”、“a”、“b”、“c”、“d”、“e”};
Map countMap=Stream.of(wordCountArr).collect(Collectors.groupby(letter->letter,Collectors.counting());
countMap.forEach((s,count)->System.out.println(s+“:”+count));

您应该有一个组合器逻辑,而不是使用putAll。必须迭代其中一个树映射,如果存在求和,然后插入,如果缺少键,则仅插入。您应该使用组合器逻辑,而不是使用putAll。必须迭代其中一个树状图,如果存在求和,然后插入,如果缺少键,则仅插入。谢谢您的回答。我知道分组的方法。如何确保类在java中是线程安全的?您需要阅读java中的线程和并发性,这个主题太大了,无法在这里讨论。但是在集合的情况下,您可以使用Collections.sychronizedXXX()确保集合是线程安全的。但是这个包装器没那么快。对于Map,有一个
ConcurrentHashMap
,它具有线程安全和惊人的性能。我知道分组的方法。如何确保类在java中是线程安全的?您需要阅读java中的线程和并发性,这个主题太大了,无法在这里讨论。但是在集合的情况下,您可以使用Collections.sychronizedXXX()确保集合是线程安全的。但是这个包装器没那么快。对于Map,有一个
ConcurrentHashMap
,具有线程安全和惊人的性能