8

我有一个方法可以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我正在寻找AOption. 然后是A我正在寻找的存在B- 也包裹在 an 中Option,否则 return ERR_1。然后如果B存在则返回它的 id,否则返回ERR_2

我想知道如何以一种简洁明了的方式(没有任何ifology)使用可选项(或模式匹配?)来实现它 - 可能是单行的。

有人可以提出一些建议吗?

可以在这里找到要试用的源代码。

4

3 回答 3

5

看起来您有 3 个可能的退出点:

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

您可以通过使用 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");
于 2016-11-17T16:34:02.850 回答
4

由于您使用的是 javaslang,因此Try似乎是一个更好的选择,因为它通过链传播错误,而 Option 仅传播其“空虚”。

如果您可以更改findAfindB返回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")))

这得到了一个 tentative B,我不确定你是否想将有效值和错误折叠成相同的值,如果是这样的话:

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

如果您在创建无意义的异常时遇到问题,您可以Either在每个查找操作中使用一个,其中左边的值是您的错误类型。这似乎更好地模拟了问题,但可能具有较长类型签名的缺点,具体取决于您如何拆分表达式。

于 2016-11-17T22:03:10.157 回答
0

您会希望将其适应您的代码,但这是我会使用的一种方法。

首先,为每个故障点隔离要封装的错误。

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);
于 2016-11-17T16:23:15.970 回答