我一直在练习java 8流和功能风格.有时我尝试使用流来解决一些编程难题.在这段时间里,我发现了一类我不知道如何用流来解决的任务,只有经典的方法.
这种任务的一个例子是:给定一个数字数组,找到元素的索引,它将使数组左边部分的总和低于零.例如,对于数组[1, 2, 3, -1, 3, -10, 9]
答案将是5
我的第一个想法是使用,IntStream.generate(0, arr.length)...
但后来我不知道如何累积值并同时意识到索引.
所以问题是:
有可能以某种方式在流上累积值然后进行有条件退出吗?
什么是并行执行?它不适合寻找我们需要了解元素顺序的索引的问题.
Alexis C... 5
我怀疑你的任务非常适合流.您正在寻找的是典型的扫描左操作,其本质上是顺序操作.
例如,想象一下管道中的以下元素:[1, 2, -4, 5]
.并行执行可以将其分成两个子部分即[1, 2]
和[-4, 5]
.那你会用它们做什么?您不能独立概括他们,因为这将产量[3]
和[1]
,然后你失去的事实1 + 2 - 4 < 0
得到尊重.
因此,即使你编写了一个跟踪索引和总和的收集器,它也无法并行执行(我怀疑你甚至可以从中受益)但你可以想象这样的收集器可以顺序使用:
public static CollectorindexSumLeft(int limit) { return Collector.of( () -> new int[]{-1, 0, 0}, (arr, elem) -> { if(arr[2] == 0) { arr[1] += elem; arr[0]++; } if(arr[1] < limit) { arr[2] = 1; } }, (arr1, arr2) -> {throw new UnsupportedOperationException("Cannot run in parallel");}, arr -> arr[0] ); }
一个简单的用法:
int index = IntStream.of(arr).boxed().collect(indexSumLeft(0));
这仍将遍历管道的所有元素,因此效率不高.
Arrays.parallelPrefix
如果数据源是数组,您也可以考虑使用它.只需计算其上的部分和,然后使用流来查找总和低于限制的第一个索引.
Arrays.parallelPrefix(arr, Integer::sum); int index = IntStream.range(0, arr.length) .filter(i -> arr[i] < limit) .findFirst() .orElse(-1);
这里也计算了所有的部分和(但是并行).
简而言之,我会使用一个简单的for循环.
我怀疑你的任务非常适合流.您正在寻找的是典型的扫描左操作,其本质上是顺序操作.
例如,想象一下管道中的以下元素:[1, 2, -4, 5]
.并行执行可以将其分成两个子部分即[1, 2]
和[-4, 5]
.那你会用它们做什么?您不能独立概括他们,因为这将产量[3]
和[1]
,然后你失去的事实1 + 2 - 4 < 0
得到尊重.
因此,即使你编写了一个跟踪索引和总和的收集器,它也无法并行执行(我怀疑你甚至可以从中受益)但你可以想象这样的收集器可以顺序使用:
public static CollectorindexSumLeft(int limit) { return Collector.of( () -> new int[]{-1, 0, 0}, (arr, elem) -> { if(arr[2] == 0) { arr[1] += elem; arr[0]++; } if(arr[1] < limit) { arr[2] = 1; } }, (arr1, arr2) -> {throw new UnsupportedOperationException("Cannot run in parallel");}, arr -> arr[0] ); }
一个简单的用法:
int index = IntStream.of(arr).boxed().collect(indexSumLeft(0));
这仍将遍历管道的所有元素,因此效率不高.
Arrays.parallelPrefix
如果数据源是数组,您也可以考虑使用它.只需计算其上的部分和,然后使用流来查找总和低于限制的第一个索引.
Arrays.parallelPrefix(arr, Integer::sum); int index = IntStream.range(0, arr.length) .filter(i -> arr[i] < limit) .findFirst() .orElse(-1);
这里也计算了所有的部分和(但是并行).
简而言之,我会使用一个简单的for循环.