参见英文答案 >
Why filter() after flatMap() is “not completely” lazy in Java streams?6个
我正在尝试编写一个方法,在列表列表中查找对象的索引并利用并行性.这是我的代码.
我正在尝试编写一个方法,在列表列表中查找对象的索引并利用并行性.这是我的代码.
// returns [i,j] where lists.get(i).get(j) equals o,or null if o is not present. public static int[] indices(List<? extends List<?>> lists,Object o) { return IntStream.range(0,lists.size()) .Boxed() .flatMap(i -> IntStream.range(0,lists.get(i).size()).mapToObj(j -> new int[]{i,j})) .parallel() .filter(a -> { System.out.println(Arrays.toString(a)); // For testing only return Objects.equals(o,lists.get(a[0]).get(a[1])); }) .findAny() .orElse(null); }
当我运行以下代码时
List<List<String>> lists = Arrays.asList( Arrays.asList("A","B","C"),Arrays.asList("D","E","F","G"),Arrays.asList("H","I"),Collections.nCopies(5,"J") ); System.out.println("Indices are " + Arrays.toString(indices(lists,"J")));
输出是这样的
[0,0] [0,1] [0,2] [3,0] [3,1] [3,3] [2,4] [1,0] [1,1] [2,1] [1,2] [1,3] Indices are [3,0]
换句话说,即使在找到对象之后搜索仍继续.是不是应该是一个短路操作?我错过了什么?此外,在迭代列表列表或锯齿状数组时,利用并行性的最佳方法是什么?
编辑
根据@ Sotirios的回答,我得到了一个输出
Thread[ForkJoinPool.commonPool-worker-3,5,main] [3,0] Thread[main,main] [2,1] Thread[ForkJoinPool.commonPool-worker-1,main] [1,0] Thread[ForkJoinPool.commonPool-worker-1,2] Thread[ForkJoinPool.commonPool-worker-1,3] Thread[main,main] [0,1] Thread[ForkJoinPool.commonPool-worker-3,1] Thread[main,2] Thread[ForkJoinPool.commonPool-worker-3,3] Thread[ForkJoinPool.commonPool-worker-3,4] Indices are [3,0]
请注意
Thread[ForkJoinPool.commonPool-worker-3,main]
在找到答案后继续搜索.
解决方法
短路操作不能保证仅产生与产生结果所需的元素一样少的元素.他们可能会这样做,但不是必需的.
flatMap的当前实现是这样的,它总是将子流的整个内容推向下游.因此,即使您的流不是并行的,您也可以看到流经流的元素多于满足findAny所需的元素.