You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何仅使用Lambda表达式改写Java Stream目标查找代码?

如何将这段流式搜索代码改写为纯Lambda形式?

我编写以下代码并非出于实用目的,更多是出于好奇(顺便提一句,我知道标题不够好,但想不出更合适的,欢迎建议)。现有代码如下:

State next = Stream.generate(q::poll).takeWhile(Objects::nonNull)
    .filter(s -> {
        if (atGoal(s)) return true;
        s.expand().forEach(q::add);
        return false;
    }).findFirst().orElse(null);

若想将其改写为仅使用Lambda表达式的形式(避免代码块),我已写出如下代码,但希望能避免其中的anyMatch(b -> true)部分:

State goal = Stream.generate(fringe::poll).takeWhile(Objects::nonNull)
    .filter(s -> atGoal(s) || s.expand().map(fringe::add).anyMatch(b -> true))
    .findFirst().orElse(null);

方案1:利用count()触发副作用并返回false

核心思路是通过count()遍历所有扩展元素(触发添加队列的副作用),再通过&& false确保这部分最终返回false,完全匹配原代码逻辑:

State goal = Stream.generate(fringe::poll)
    .takeWhile(Objects::nonNull)
    .filter(s -> atGoal(s) || (s.expand().map(fringe::add).count() > 0 && false))
    .findFirst().orElse(null);
  • 当s是目标状态时,atGoal(s)为true,filter返回true,直接被findFirst捕获
  • 当s不是目标状态时,执行s.expand().map(fringe::add).count():遍历所有扩展元素并加入队列,随后count() > 0 && false最终返回false,filter过滤掉该元素,继续循环

方案2:用peek替代map更贴合语义

既然我们只是要执行“添加到队列”的副作用操作,用peek比map更合适,配合findAny().isPresent()触发执行,再通过&& false返回false:

State goal = Stream.generate(fringe::poll)
    .takeWhile(Objects::nonNull)
    .filter(s -> atGoal(s) || (s.expand().peek(fringe::add).findAny().isPresent() && false))
    .findFirst().orElse(null);
  • peek(fringe::add)直接对每个扩展元素执行入队操作,无需映射为Boolean类型,语义更清晰
  • 无论s.expand()是否为空,findAny().isPresent() && false都会返回false,确保非目标状态的元素被过滤

方案3:单行Lambda代码块(兼容Java所有版本)

如果允许Lambda使用代码块但保持单行形式,这是最直观且易读的写法,完全还原原代码逻辑:

State goal = Stream.generate(fringe::poll).takeWhile(Objects::nonNull).filter(s -> { boolean g = atGoal(s); if(!g) s.expand().forEach(fringe::add); return g; }).findFirst().orElse(null);

内容的提问来源于stack exchange,提问作者traveh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 10:45:39