BiFunction-apply方法应始终返回第二个参数。为什么?

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]

Era*_*ran 6

您正在执行的缩减-使用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),添加1List并返回2(这成为新的中间结果)。下一次迭代将添加2到,List然后返回3。等等...

第二个代码段调用accumulator.apply(1,2),将添加1List并返回1(仍然是新的中间结果)。下一次迭代将添加1到,List然后再次返回1。等等...

总而言之,您的两个累加函数具有不同的功能:

第一个结果在中的最后一个元素中Stream(因为它会不断丢弃当前结果并将其替换为当前元素)。

第二个结果产生的第一个元素Stream(因为它保留第一个元素并忽略所有其他元素)。