如何清理Java 8流“ findFirst()”结果,即使为空

时间:2018-12-11 22:04:23

标签: java java-8 java-stream optional

我经常会发现与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);
}

您能想到一种方法来在流中包含第一个条件而不使其变得更复杂吗?

2 个答案:

答案 0 :(得分:4)

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

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

编辑:

至:

  

您能想到一种在流中包含第一个条件的方法吗   没有使其变得更复杂?

否,这样做更好。它更具可读性且易于遵循。

将任何类型的逻辑引入到一个管道中(如果可能的话,则为 )将仅仅是复杂的结束,因此更难以理解和理解。

答案 1 :(得分:3)

您可以通过以下方式在一条语句中完成

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 -> true将接受任何元素,这将导致唯一元素被按预期接受。否则,将使用普通谓词pt -> pt.getAutoBill() == AutoBill.N || pt.getAutoBill() == null