【发布时间】:2015-11-21 02:26:33
【问题描述】:
我正在尝试编写一种方法,该方法在列表列表中查找对象的索引并利用并行性。这是我的代码。
// 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, 2]
[3, 3]
[2, 0]
[3, 4]
[1, 0]
[1, 1]
[2, 1]
[1, 2]
[1, 3]
Indices are [3, 0]
换句话说,即使在找到对象之后,搜索也会继续。 findAny 不应该是短路操作吗?我错过了什么?另外,在迭代列表列表或锯齿状数组时,利用并行性的最佳方法是什么?
编辑
按照@Sotirios 的回答中的想法,我得到了输出
Thread[ForkJoinPool.commonPool-worker-3,5,main] [3, 0]
Thread[main,5,main] [2, 0]
Thread[main,5,main] [2, 1]
Thread[ForkJoinPool.commonPool-worker-1,5,main] [1, 0]
Thread[ForkJoinPool.commonPool-worker-1,5,main] [1, 1]
Thread[ForkJoinPool.commonPool-worker-1,5,main] [1, 2]
Thread[ForkJoinPool.commonPool-worker-1,5,main] [1, 3]
Thread[main,5,main] [0, 0]
Thread[main,5,main] [0, 1]
Thread[ForkJoinPool.commonPool-worker-3,5,main] [3, 1]
Thread[main,5,main] [0, 2]
Thread[ForkJoinPool.commonPool-worker-3,5,main] [3, 2]
Thread[ForkJoinPool.commonPool-worker-3,5,main] [3, 3]
Thread[ForkJoinPool.commonPool-worker-3,5,main] [3, 4]
Indices are [3, 0]
注意
Thread[ForkJoinPool.commonPool-worker-3,5,main]
即使在找到答案后仍继续搜索。
【问题讨论】:
-
使用 findFirst() 代替。
-
@TaharBakir 它仍在继续搜索。
-
另外,并行性可能需要一些时间才能让一个线程通知其他线程他们不需要继续运行。
-
@LouisWasserman 当我按照 Sotirios 的回答打印线程时,我发现即使在同一个线程中,在找到对象后搜索也会继续。
标签: java java-8 java-stream