Объединить необязательные списки - PullRequest
3 голосов
/ 15 марта 2019

У меня есть три дополнительных>, которые должны быть объединены и возвращены. Я пытался использовать 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
}

Есть мысли о том, как это сделать эффективно?

Ответы [ 3 ]

3 голосов
/ 15 марта 2019

Что-то вроде:

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()));
1 голос
/ 16 марта 2019

Я полагаю, что вы не хотите возвращать 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());
}

Несколько других ответов используют isPresent и get. Они низкого уровня, и они нам здесь не нужны.

Однако нам абсолютно не нужна потоковая операция. Вот возможность без этого:

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;
}
1 голос
/ 15 марта 2019

Это становится проще, когда вы используете поток:

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, и пусть поток возвращает пустой список, когда необязательный ввод не является присутствует .

...