Concatenate Optional Lists

一笑奈何 提交于 2020-11-28 10:47:35

问题


I have three Optional> which have to be combined and returned. I tried to use Optional.map() and flatmap() but was not successful.

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
}

Any thoughts on how to do is efficiently?


回答1:


Something like :

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

or rather more readable as :

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



回答2:


It gets easier when you use a stream:

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

Important to note that this optional won't ever be empty. It will contain at least an empty list, which defeats the purpose of using optionals. When using Collection types as return types, Optional are not really used because it's recommended to return an empty collection where an empty optional would be used.

So I would just change the method's return type to List and let the stream return an empty list when no input optional is present.




回答3:


I suggest that you don’t want to return an Optional from your method. In case there are no records in any of the three entity lists, the caller would prefer just to have an empty list.

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

A couple of the other answers use isPresent and get. They are low-level, and we don’t need them here.

We don’t absolutely need the stream operation, though. Here’s a possibility without it:

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;
}


来源:https://stackoverflow.com/questions/55186324/concatenate-optional-lists

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!