我经常会发现与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);
}
您能想到一种方法来在流中包含第一个条件而不使其变得更复杂吗?
答案 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
。