简体   繁体   English

如何使用optionals实现这个嵌套流?

[英]How to implement this nested flow with optionals?

I've have a method that takes String as an input and should also return a String . 我有一个方法,它将String作为输入,并且还应该返回一个String

The following ASCII art presents the logical flow: 以下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

Basically for given input I'm looking for A object which is returned wrapped in an Option . 基本上对于给定的input我正在寻找A包装在Option Then is A is present I'm looking for B - wrapped in an Option too, otherwise return ERR_1 . 然后是A存在我正在寻找B - 包裹在一个Option ,否则返回ERR_1 Then if B is present return it's id, otherwise return ERR_2 . 然后如果B存在则返回它的id,否则返回ERR_2

I'm wondering how it could be implemented using optionals (or pattern matching maybe?) in a nice and concise way (without any ifology ) - possibly in one-liner. 我想知道如何使用选项(或模式匹配可能?)以一种简洁的方式(没有任何ifology )实现 - 可能是单行。

Could anyone please suggest something? 有人可以建议吗?

Source code to try out can be found here . 可以在这里找到试用的源代码。

It looks like you have 3 possible exit points: 看起来您有3个可能的退出点:

  1. optA empty -> "ERR_1" optA empty - >“ERR_1”
  2. optA not empty && optB empty -> "ERR_2" optA不为空&& optB为空 - >“ERR_2”
  3. both not empty -> optB.get().bid 两者都不为空 - > optB.get()。bid

You can achieve this by doing this with Javaslang: 你可以通过使用Javaslang来实现这一点:

 optA
   .map(a -> finder.findB(a.bid)
      .map(b -> b.bid)
      .getOrElse("ERR_2"))
   .getOrElse("ERR_1");

If optA is empty, we will jump straight to orElse("ERR_1") 如果optA为空,我们将直接orElse("ERR_1")

If optA is not empty, we are using the value stored inside for getting value b.bid or "ERR_2" in case of optB emptiness. 如果optA不为空,我们使用存储在其中的值来获取值b.bid"ERR_2"以防optB空白。

Also, in pure Java 8, it would look like this: 此外,在纯Java 8中,它看起来像这样:

optA
  .map(a -> finder.findB(a.bid)
    .map(b -> b.bid)
    .orElse("ERR_2"))
  .orElse("ERR_1");

Since you're using javaslang, Try seems to be a better choice because it propagates the error throught the chain, while Option only propagates its "emptiness". 因为你正在使用javaslang,所以Try似乎是一个更好的选择,因为它通过链传播错误,而Option只传播它的“空虚”。

If you can change findA and findB to return Try you get: 如果你可以改变findAfindB返回Try你得到:

Try<B> b = finder.findA(input)
    .flatMap(a -> finder.findB(a.bid))

If you can't, then: 如果你不能,那么:

Try<B> b = finder.findA(input).toTry(() -> new Exception("ERR_1"))
    .flatMap(a -> findB(a.bId).toTry(() -> new Exception("ERR_2")))

That gets a tentative B , I'm unsure if you want to collapse the valid value and the error into the same value, if that's the case then: 得到一个暂定的B ,我不确定你是否要将有效值和错误折叠成相同的值,如果是这样的话:

String value = b.getOrElseGet(Throwable::getMessage)

If you have an issue with creating pointless exceptions, you can use an Either in each of the find operations, where the left value is your error type. 如果您在创建无意义异常时遇到问题,可以在每个查找操作中使用Either ,其中左侧值是您的错误类型。 That seems to model the problem better, but may have the downside of longer type signatures, depending on how you split up the expressions. 这似乎可以更好地模拟问题,但可能会有较长类型签名的缺点,具体取决于您如何拆分表达式。

You'll want to adapt this to your code, but this is an approach I'd use. 您需要将其调整为您的代码,但这是我使用的方法。

First, isolate the errors you want to encapsulate for each point of failure. 首先,隔离要为每个故障点封装的错误。

Supplier<? extends RuntimeException> missingAException = IllegalStateException::new;
Supplier<? extends RuntimeException? missingBException = IllegalStateException::new;

Doing this allows you to write a lambda later on to provide a specific error message if you so desire. 这样做允许您稍后编写lambda以提供特定的错误消息,如果您愿意的话。

Now, we write the optionals. 现在,我们编写选项。

Optional<A> optA = finder.find(input);
Optional<B> optB = finder.findB(optA.orElseThrow(missingAException));

To extract optB , use the same pattern as we did for optA . 为了提取optB ,因为我们没有使用相同的模式optA

B value = optB.orElseThrow(missingBException);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM