[英]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.