Java Stream有状态行为示例

时间:2017-05-25 03:26:24

标签: java parallel-processing synchronization java-stream

java.util.stream的{​​{3}}声明如下:

  

有状态lambda的一个例子是map()中的参数:

Set<Integer> seen = Collections.synchronizedSet(new HashSet<>());
stream.parallel().map(e -> { if (seen.add(e)) return 0; else return e; })...
     

这里,如果映射操作是并行执行的,由于线程调度的差异,相同输入的结果可能因运行而异,而对于无状态lambda表达式,结果将始终相同。

我不明白为什么这不会产生一致的结果,因为该集合是同步的,并且一次只能处理一个元素。您是否可以通过演示结果因并行化而变化的方式完成上述示例?

2 个答案:

答案 0 :(得分:3)

List<Integer> numbers = // fill it in with [1, 3, 3, 5]
List<Integer> collected = numbers.stream().parallel().map(...).collect(Collectors.toList());

collected可以包含[0,0,3,0]或[0,3,0,0],具体取决于首先处理的中间两个元素中的哪一个。

答案 1 :(得分:2)

我不确定这是否属于有状态本身(如果不是我只会删除它),而是依赖于map内有状态的任何等等很糟糕。

int[] arr = new int[3];
    Stream.of(1, 2, 3)
            .map(i -> {
                arr[i] = i + 5;
                return i * 2;
            })
            .count();

    System.out.println(Arrays.toString(arr));

在jdk-9中,这将生成一个仅包含零的数组,因为没有更改Stream大小(flatmapfilter)的操作,因此永远不会执行map