【问题标题】:Return a List of present objects from a List of Optional objects using Lightweight-Stream-API使用 Lightweight-Stream-API 从可选对象列表中返回当前对象列表
【发布时间】:2017-05-11 15:06:33
【问题描述】:

假设我有一个 Optional 对象的数组列表,例如 List<Visit> visit = {Optional[Visit], Optional[Visit], ...}。如何从Optional 获取Visit 对象并将这些对象作为List 返回?

我尝试过这样的事情:

return Stream.of(visits).filter(value -> Optional.isPresent(value))
    .map((Visit t) -> Optional.get(t))
    .collect(Collectors.toList());

还有这个:

return Stream.of(visits)
   .map(visit -> Optional.of(visit).get())
   .collect(Collectors.toList());

但这不能编译。

我正在尝试使用Lightweight-Stream-API 作为流库。

【问题讨论】:

  • 你的版本其实没问题,只要你能把它解压成一个单独的函数。当然,您可以使用flatMap,但我建议重构您的代码以将List<Optional<Visit>> 替换为List<Visit>
  • 您的代码无法编译,因为没有静态方法Optional.isPresent(Object)isPresentget 都是实例方法。也不清楚你想通过调用Optional.of(t).get() 来做什么 - 这段代码几乎毫无意义,因为有很多更清晰和可读的方式来抛出NullPointerException
  • @M.Prokhorov 让我试着正确解释我想要达到的目标。我打电话回应。在 API 调用之后从方法中获取 getVisits()。并且返回类型是 List 但列表中的每个 Visit 对象都用 Optional 包装。所以我基本上试图从可选中获取值并将它们添加到一个新列表中,该列表只包含没有可选的访问。
  • @irobotxxx 我打算写一个更简单的答案,但是visits 的类型是什么?我似乎很困惑是List<Visit>还是List<Optional<Visit>>
  • @irobotxxx,如果它是List<Visit>,那么对象就不能被“包装”成一个可选项,因为那样它就是List<Optional<Visit>>。我还坚持认为您应该更改代码,以便它不会 包装成一个可选项。除了让开发人员生气和困惑之外,这个数据结构(可选列表)没有任何目的。

标签: java android lightweight-stream-api


【解决方案1】:

你可以这样做:

List<Visit> visitsWithoutOptionals = visits.stream()
    .filter(Optional::isPresent)
    .map(Optional::get)
    .collect(Collectors.toList());

【讨论】:

    【解决方案2】:

    你可以这样做:

    return visits.stream()
                 .map(visit -> visit.orElse(null))
                 .filter(Objects::nonNull)
                 .collect(Collectors.toList());
    

    假设visits 的类型为List&lt;Optional&lt;Visit&gt;&gt;

    代码无法编译的原因

    假设变量visits 的类型为List&lt;Optional&lt;Visit&gt;&gt; 您发布的语句:

    Stream.of(visits).filter(value -> Optional.isPresent(value))
                     .map((Visit t) -> Optional.get(t))
                     .collect(Collectors.toList());
    

    有以下问题:

    1. Stream.of() 采用T 类型的一个或多个元素并创建一个。您使用visits 作为List&lt;Optional&lt;Visit&gt;&gt; 类型的一个元素,我认为您打算获得Optional&lt;Visit&gt;Stream,您可以通过使用visits.stream() 来实现。

    2. filter(value -&gt; Optional.isPresent(value)) 确实以静态方式调用 isPresent(T t),而方法 isPresent(T t) 不存在,既不是静态方法也不是实例方法。我想你打算做的是:filter(value -&gt; value.isPresent()) 等于filter(Optional::isPresent)。第二种的区别是Optional::isPresent不调用静态方法,而是产生方法引用。

    3. map((Visit) t -&gt; Optional.get(t)) 也以不存在的静态方式调用 get(T t) 方法,既不是静态的,也不是实例方法。我认为您打算调用等于map(Optional::get)map((Visit) t -&gt; t.get())

    解决这些问题将产生新的声明:

    visits.stream().filter(Optional::isPresent)
                   .map(Optional::get)
                   .collect(Collectors.toList());
    

    与我的解决方案的不同之处仅在于您在过滤后进行映射。作为一个正确理解它的读者,您需要记住Optional::get 将始终返回一个 non-null 值。如果您先映射然后过滤,则不必记住没有 null 值,因为您在第二步中将它们过滤掉。

    【讨论】:

    • 感谢您的回复,但您能否查看我上面的 cmets 以澄清我正在尝试做什么
    • 感谢您的详细回复。我仍在掌握新的 Java 8 API 功能。我将这些标记为已接受的答案,也是因为详细的解释。
    猜你喜欢
    • 2023-03-19
    • 1970-01-01
    • 2017-09-26
    • 2020-12-07
    • 1970-01-01
    • 2016-01-26
    • 1970-01-01
    相关资源
    最近更新 更多