连接可选列表

Concatenate Optional Lists

我有三个 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
}

关于如何高效地做事有什么想法吗?

类似于:

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()));

使用流时会变得更容易:

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

重要的是要注意这个可选的永远不会是空的。它将至少包含一个空列表,这违背了使用可选值的目的。当使用 Collection 类型作为 return 类型时,Optional 并没有真正被使用,因为它被推荐给 return 一个 empty 集合,其中一个空可选的将被使用。

所以我只是将方法的 return 类型更改为 List 并在没有输入可选 present[=22 时让流 return 成为一个空列表=].

我建议您不要从您的方法中 return 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;
}