[英]How to implement this nested flow with optionals?
我有一個方法,它將String
作為輸入,並且還應該返回一個String
。
以下ASCII藝術介紹了邏輯流程:
Option<A> optA = finder.findA(input);
optA
/\
isEmpty() / \ isDefined()
/ \
"ERR_1" Option<B> optB = finder.findB(optA.get().bid);
/ \
isEmpty() / \ isDefined()
/ \
"ERR_2" opt2.get().id
基本上對於給定的input
我正在尋找A
包裝在Option
。 然后是A
存在我正在尋找B
- 包裹在一個Option
,否則返回ERR_1
。 然后如果B
存在則返回它的id,否則返回ERR_2
。
我想知道如何使用選項(或模式匹配可能?)以一種簡潔的方式(沒有任何ifology )實現 - 可能是單行。
有人可以建議嗎?
可以在這里找到試用的源代碼。
看起來您有3個可能的退出點:
你可以通過使用Javaslang來實現這一點:
optA
.map(a -> finder.findB(a.bid)
.map(b -> b.bid)
.getOrElse("ERR_2"))
.getOrElse("ERR_1");
如果optA
為空,我們將直接orElse("ERR_1")
如果optA
不為空,我們使用存儲在其中的值來獲取值b.bid
或"ERR_2"
以防optB
空白。
此外,在純Java 8中,它看起來像這樣:
optA
.map(a -> finder.findB(a.bid)
.map(b -> b.bid)
.orElse("ERR_2"))
.orElse("ERR_1");
因為你正在使用javaslang,所以Try
似乎是一個更好的選擇,因為它通過鏈傳播錯誤,而Option只傳播它的“空虛”。
如果你可以改變findA
和findB
返回Try
你得到:
Try<B> b = finder.findA(input)
.flatMap(a -> finder.findB(a.bid))
如果你不能,那么:
Try<B> b = finder.findA(input).toTry(() -> new Exception("ERR_1"))
.flatMap(a -> findB(a.bId).toTry(() -> new Exception("ERR_2")))
得到一個暫定的B
,我不確定你是否要將有效值和錯誤折疊成相同的值,如果是這樣的話:
String value = b.getOrElseGet(Throwable::getMessage)
如果您在創建無意義異常時遇到問題,可以在每個查找操作中使用Either
,其中左側值是您的錯誤類型。 這似乎可以更好地模擬問題,但可能會有較長類型簽名的缺點,具體取決於您如何拆分表達式。
您需要將其調整為您的代碼,但這是我使用的方法。
首先,隔離要為每個故障點封裝的錯誤。
Supplier<? extends RuntimeException> missingAException = IllegalStateException::new;
Supplier<? extends RuntimeException? missingBException = IllegalStateException::new;
這樣做允許您稍后編寫lambda以提供特定的錯誤消息,如果您願意的話。
現在,我們編寫選項。
Optional<A> optA = finder.find(input);
Optional<B> optB = finder.findB(optA.orElseThrow(missingAException));
為了提取optB
,因為我們沒有使用相同的模式optA
。
B value = optB.orElseThrow(missingBException);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.