Wal*_*all 3 java lambda java-stream
我试图从列表中识别其前任大于其值的数字。
在lambda表达式中,如果我返回b,则其行为符合预期,但如果我返回a,则给出错误的输出。
这两个return语句有什么区别?
List<Integer> list = Arrays.asList(1,2,3,4,5,8,7);
List<Integer> result = new ArrayList<>();
list.stream().reduce((a,b) -> {if (a < b) result.add(a);return b;});
System.out.println(result);
result.clear();
list.stream().reduce((a,b) -> {if (a < b) result.add(a);return a;});
System.out.println(result);
Run Code Online (Sandbox Code Playgroud)
输出:
[1、2、3、4、5]
[1,1,1,1,1,1]
您正在执行的缩减-使用Optional<T> java.util.stream.Stream.reduce(BinaryOperator<T> accumulator)-等效于以下伪代码(取自Javadoc):
boolean foundAny = false;
T result = null;
for (T element : this stream) {
if (!foundAny) {
foundAny = true;
result = element;
} else {
result = accumulator.apply(result, element);
}
}
return foundAny ? Optional.of(result) : Optional.empty();
Run Code Online (Sandbox Code Playgroud)
正如可以看到,在中间result的减少作为蓄能器的第一个参数和电流通过element所述的Stream作为第二个参数被传递。
因此,当您的lambda表达式返回第二个参数b(第一个代码段)时,中间结果将成为的当前元素Stream,您将List在下一次迭代时将其添加到中。
当您的lambda返回第一个参数a(第二个代码段)时,中间结果保持不变(始终1是的第一个元素Stream),并且您一直将该值添加到中List。
让我们用实际数字进行验证:
result被初始化为Stream的第一个元素1。
然后,第一个代码片段调用accumulator.apply(1,2),添加1到List并返回2(这成为新的中间结果)。下一次迭代将添加2到,List然后返回3。等等...
第二个代码段调用accumulator.apply(1,2),将添加1到List并返回1(仍然是新的中间结果)。下一次迭代将添加1到,List然后再次返回1。等等...
总而言之,您的两个累加函数具有不同的功能:
第一个结果在中的最后一个元素中Stream(因为它会不断丢弃当前结果并将其替换为当前元素)。
第二个结果产生的第一个元素Stream(因为它保留第一个元素并忽略所有其他元素)。