【问题标题】:Stream in orElse of optional流入 orElse 的可选
【发布时间】:2018-11-21 16:11:04
【问题描述】:

我正在尝试在 orElse 中使用 Stream 并且难以理解错误。

collectorConfiguration = Optional.ofNullable(recapPlacement.getAttId())
    .map(attId -> Optional.ofNullable(processorEngine.buildFrimFromAttId(attId))
         .orElseThrow( () -> new OmegaException("UnableToFirmByAttId", recapPlacement.getAttId())))
    .orElse( () -> Optional.ofNullable(collectorConfigurations.stream() //getting error here
        .filter(cc -> recapPlacement.getPnetCode().equals(cc.getPnetCode()))
        .filter(Objects::nonNull)
        .findFirst())
        .orElseThrow( () -> new OmegaException("CollectorCouldNotMapForPnetCode", recapPlacement.getPnetCode()))
    );

在上面的代码中我正在尝试

  1. 如果attId 不为空,则获取collectorConfig

  2. 如果attId 不为空且collectorConfig 未找到该attId,那么我将抛出异常

  3. 如果attId 为空,那么我使用pnet 代码通过流collectConfigurations 列表获取collectConfig

  4. 如果 collectConfig 未找到 pnetCode,那么我将抛出异常

它在 orElse 块中给出了编译错误“Target type of a lambda expression must be an interface”。

【问题讨论】:

  • 错误是什么?
  • lambda 表达式的目标类型必须是接口
  • 编译复杂的流管道可能很棘手。有一些通常有用的解决问题的技术:1)向所有 lambdas 添加参数类型:(ArgType arg) -> ...。 2) 为方法添加显式类型参数:<ArgType>.orElse(...)。 3) 将整个 lambdas 提取到局部变量。本地人通常看起来像这样:Function<Arg1, Arg2> = ...,这使得设置显式类型参数变得容易。应用这些技术通常会产生更精确的编译错误并帮助您找到问题。问题解决后,可以删除辅助类型和变量。
  • 代码中用到了哪些变量?
  • 我建议对 recapPlacement.getAttId() 的结果使用普通的旧 if-else 测试。 Stream 很好,但是您在此处使用 Optional 的方式违反了它的 API 说明和作者的建议。请参阅The Mother of All Bikesheds 了解一些使您的代码可读的方法。

标签: java java-8 java-stream optional


【解决方案1】:

你可能想替换

.orElse( () -> Optional.ofNullable(collectorConfigurations.stream() //getting error here

Optional.orElseGet 期望 Supplier 为:

.orElseGet( () -> Optional.ofNullable(collectorConfigurations.stream() ...

除了上述之外,您应该不需要供应商中的Optional.ofNullable

.orElseGet( () -> collectorConfigurations.stream()
    .filter(cc -> recapPlacement.getPnetCode().equals(cc.getPnetCode()))
    .filter(Objects::nonNull) //non-null filtered
    .findFirst()) // optional
    .orElseThrow( () -> new OmegaException("CollectorCouldNotMapForPnet...

【讨论】:

  • .OrElseGet() 期待收集器配置,但由于我在其上使用 Optional(),它会抛出错误的返回类型编译错误
  • 确保将() -> 用作.orElseGet(()->...) 的一部分。
  • 我肯定会用的
  • 是的,这是一个错误。我认为我需要可选的抛出异常
【解决方案2】:

orElse 采用常规值,而不是任何可以用 lambda 表示的值。简单地删除 () -> 应该会有所帮助。或者,您可能打算致电orElseGet

【讨论】:

  • 如果我删除 '() ->' 那么它将是 Optional() 不会被 orElse 排除
  • @arjun OK;我们没有足够的代码来推断这里预期的类型,但是整个可选选项的包装似乎没有必要。为什么将stream() 调用的结果包装在可选中?那永远不会返回 null。
  • 抱歉打错了。我添加了它,以便我可以在 Optional().orElseThrow 上抛出异常
  • 是的,这是个错误。我认为我需要可选的抛出异常
猜你喜欢
  • 2015-05-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-15
  • 1970-01-01
相关资源
最近更新 更多