【问题标题】:Concatenate Optional Lists连接可选列表
【发布时间】:2019-03-15 15:52:10
【问题描述】:

我有三个 Optional> 必须合并并返回。我尝试使用Optional.map()flatmap(),但没有成功。

public Optional<List<Entiy>> getRecords() {
    Optional<List<Entiy>> entity1 = repo.findAllByStatus("1");
    Optional<List<Entiy>> entity2 = repo.findAllByStatus("2");
    Optional<List<Entiy>> entity3 = repo.findAllByStatus("3");
    //Need to return a concatenation of entity1, 2 and 3
}

关于如何高效地做的任何想法?

【问题讨论】:

  • 为什么要返回Optional?如果没有记录,调用者肯定更喜欢空列表吗?
  • @OleV.V.没错。

标签: java java-8 optional


【解决方案1】:

使用流会更容易:

return Stream.of(entity1, entity2, entity3)
        .filter(Optional::isPresent)
        .map(Optional::get)
        .flatMap(List::stream)
        .collect(Collectors.collectingAndThen(Collectors.toList(), Optional::of));

需要注意的是,此可选选项永远不会为空。它将至少包含一个空列表,这违背了使用选项的目的。当使用 Collection 类型作为返回类型时,Optional 并没有真正使用,因为建议返回一个 empty 集合,其中将使用一个空的可选项。

所以我只需将方法的返回类型更改为List,并在没有可选输入存在时让流返回一个空列表。

【讨论】:

    【解决方案2】:

    类似:

    return Optional.of(Stream.of(entity1.orElse(new ArrayList<>()), entity2.orElse(new ArrayList<>()), entity3.orElse(new ArrayList<>()))
                .flatMap(List::stream)
                .collect(Collectors.toList()));
    

    或者更易读为:

    return Optional.of(Stream.of(entity1, entity2, entity3)
            .filter(Optional::isPresent)
            .map(Optional::get)
            .flatMap(List::stream)
            .collect(Collectors.toList()));
    

    【讨论】:

    • Collections.emptyList
    • 你不需要用方法引用做所有事情,有时候,一个 lambda 表达式也不错,return Optional.of( Stream.of(entity1, entity2, entity3) .flatMap(o -&gt; o.map(List::stream).orElse(null)) .collect(Collectors.toList()) );
    【解决方案3】:

    我建议您不要从您的方法中返回 Optional。如果三个实体列表中的任何一个都没有记录,调用者宁愿只拥有一个空列表。

    public List<Entity> getRecords() {
        return Stream.of("1", "2", "3")
                .map(repo::findAllByStatus)
                .flatMap(el -> el.map(List::stream).orElse(Stream.empty()))
                .collect(Collectors.toList());
    }
    

    其他几个答案使用isPresentget。它们是低级的,我们在这里不需要它们。

    不过,我们并不绝对需要流操作。这是没有它的可能性:

    public List<Entity> getRecords() {
        List<Entity> concatenation = new ArrayList<>();
        repo.findAllByStatus("1").ifPresent(concatenation::addAll);
        repo.findAllByStatus("2").ifPresent(concatenation::addAll);
        repo.findAllByStatus("3").ifPresent(concatenation::addAll);
        return concatenation;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-09-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-04-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多