Efficient way to take a Set of Lists, find their common elements, and sort the results using Java 8 streams

Viewed 94

I've got an idea of how this could work, but it seems like there must be a more elegant way of doing this.

Set<List<SearchResult>> searchResults = new HashSet<>();
…
return searchResults.stream()
    .reduce((sr1, sr2) -> {
        sr1.retainAll(sr2);
        return sr1;
    })
    .get().stream()
    .sorted(Comparator.comparing(SearchResult::getDocno))
    .collect(Collectors.toList());

I'm streaming the Set, finding the intersection with retainAll() — so far, so good. But then Optional.get() needs to be streamed again so I can sort it. That doesn't seem right. Plus, my IDE suggests I need an isPresent() check, but I'm not sure how to fit that in.

Note: I can easily do this with loops, but I'm more interested in learning to work with streams.

1 Answers

You were very close IMO, it's just that reduce needs to return a new Object all the time:

searchResults
            .stream()
            .reduce((left, right) -> {
                List<SearchResult> list = new ArrayList<>(left);
                list.retainAll(right);
                return list;
            })
            .orElse(Collections.emptyList())
            .stream()
            .sorted(Comparator.comparing(SearchResult::getDocno))
            .collect(Collectors.toList());
Related