【问题标题】:How to cleanly process java 8 stream "findFirst()" result even if empty即使为空,如何干净地处理 java 8 流“findFirst()”结果
【发布时间】:2018-12-11 22:04:22
【问题描述】:

我经常发现与 java 8 流混淆的一个方面是中间结果可能为空,如果它为空或不为空,您需要采用备用路径。

例如,如果我有这样的代码:

String pymtRef = defaultValue;
Optional<PaymentTender> paymentTender = paymentTenders.stream()
        .filter(pt -> (pt.getFlag() == Flag.N || pt.getFlag() == null)).findFirst();
if (paymentTender.isPresent()) {
    pymtRef = paymentTender.get().getId();
}
return pymtRef;

我想弄清楚如何删除条件块并在单个流中执行此操作。

如果我只是在过滤结果上调用“.map”,如果它找到匹配的条目就可以工作。如果没有,我会收到 NoSuchElementException。

我可能会改用“ifPresent()”,但它的返回类型是“void”。

有什么方法可以让这个更干净吗?

更新

使用“orElse()”的解决方案效果很好。

整个方法现在看起来像这样:

public String getPaymentReference(OrderContext orderContext) {
    List<PaymentTender> paymentTenders = getPaymentTenders(orderContext);
    if (paymentTenders.size() == 1) {
        return paymentTenders.get(0).getId();
    }
    return paymentTenders.stream()
            .filter(pt -> (pt.getAutoBill() == AutoBill.N || pt.getAutoBill() == null))
            .findFirst().map(pt -> pt.getId()).orElse(DEFAULT_VALUE);
}

你能想出一种方法在流中包含第一个条件而不使其更复杂吗?

【问题讨论】:

    标签: java java-8 java-stream optional


    【解决方案1】:

    map 之后直接调用 get() 如果 Optional 的状态为空,则会产生异常,而是在 map 之后调用 orElse 并提供默认值:

    paymentTenders.stream()
                .filter(pt -> (pt.getFlag() == Flag.N || pt.getFlag() == null))
                .findFirst()
                .map(PaymentTender::getId)
                .orElse(someDefaultValue);
    

    编辑:

    至于:

    你能想出一种方法在流中包含第一个条件吗 不让它变得更复杂?

    不,这比你做的更好。它更易读,更容易理解。

    引入任何类型的逻辑以使其成为一个管道(如果可能)只会变得复杂,因此更难遵循和理解。

    【讨论】:

    • 优秀。更新帖子,进一步完善问题。
    • @DavidM.Karr 老实说。我建议继续你目前的方法。见编辑。
    【解决方案2】:

    你可以在一个语句中通过

    public String getPaymentReference(OrderContext orderContext) {
        List<PaymentTender> paymentTenders = getPaymentTenders(orderContext);
        return paymentTenders.stream()
            .filter(paymentTenders.size() == 1? pt -> true:
                    pt -> pt.getAutoBill() == AutoBill.N || pt.getAutoBill() == null)
            .findFirst().map(PaymentTender::getId).orElse(DEFAULT_VALUE);
    }
    

    请注意,这不会对每个元素重复评估paymentTenders.size() == 1,而是根据状态使用不同的函数。当条件满足时,pt -&gt; true 将接受任何元素,这将导致唯一的元素按预期被接受。否则,使用普通谓词pt -&gt; pt.getAutoBill() == AutoBill.N || pt.getAutoBill() == null

    【讨论】:

    • 已确认。我认为在这种情况下,我会坚持使用稍微冗长的版本,但当它更适合时,我会记住这种替代 lambdas 的技术。
    猜你喜欢
    • 2017-11-11
    • 1970-01-01
    • 2011-07-22
    • 2010-10-20
    • 1970-01-01
    • 1970-01-01
    • 2011-08-17
    • 2021-07-14
    • 2021-10-22
    相关资源
    最近更新 更多