为了账号安全,请及时绑定邮箱和手机立即绑定

BiFunction - apply 方法应该总是返回第二个参数。为什么?

BiFunction - apply 方法应该总是返回第二个参数。为什么?

子衿沉夜 2023-05-10 13:49:10
我正在尝试从其前身大于其价值的列表中识别数字。在 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);输出:[1, 2, 3, 4, 5][1, 1, 1, 1, 1, 1]
查看完整描述

2 回答

?
白衣非少年

TA贡献1155条经验 获得超0个赞

您正在执行的减少 - 使用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();

如您所见,归约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(因为它保留第一个元素并忽略所有其他元素)。


查看完整回答
反对 回复 2023-05-10
?
动漫人物

TA贡献1815条经验 获得超10个赞

这不是您问题的直接答案,但由于我说有状态过滤器会更好,所以我觉得有必要展示它。采用以下有状态谓词:


public class GreaterThanPreceding implements Predicate<Integer> {

    private Integer preceding = null;


    @Override

    public boolean test(Integer current) {

        boolean greaterThan = preceding == null || (current > preceding);

        preceding = current;

        return greaterThan;

    }

}

这样,流操作将如下所示:


List<Integer> collected = list.stream()

        .filter(new GreaterThanPreceding())

        .collect(Collectors.toList());

System.out.println(collected);


查看完整回答
反对 回复 2023-05-10
  • 2 回答
  • 0 关注
  • 93 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信