然后将它们全部合并

然后将它们全部合并

有没有更优雅的方法从单个流中收集更多列表,然后将它们全部合并?

这是我想出的:

    private Set<Long> getAllIds(List<MyClass> fetchedElements) {
        Set<Long> myIds = new HashSet<>();
        myIds.addAll(fetchedItems.stream().map(MyClass::getBlueId).collect(Collectors.toList()));
        myIds.addAll(fetchedItems.stream().map(MyClass::getRedId).collect(Collectors.toList()));
        myIds.addAll(fetchedItems.stream().map(MyClass::getGreenId).collect(Collectors.toList()));
        return myIds;
    }


在我看来,当我查看这三行代码时,因为那里存在代码重复,但是我没有找到一种方法来加入我正在对流进行的不同映射操作。

感谢您的帮助!

最佳答案

使用flatMap

fetchedElements.stream()
        .flatMap(item -> Stream.of(item.getBlueId(), item.getRedId(), item.getGreenId()))
        .collect(Collectors.toSet());


请注意,评估顺序为BRGBRG而不是BBRRGG,当然,由于使用的是Set,输出顺序是不确定的。我认为这没关系。



您可以使此方法更通用:

private Set<Long> getAllIds(List<MyClass> fetchedElements,
        List<Function<MyClass, Long>> extractors) {
    return fetchedElements.stream()
            .flatMap(item -> extractors.stream().map(f -> f.apply(item)))
            .collect(Collectors.toSet());
}


致电:

 Set<Long> myIds = getAllIds(fetchedElements, List.of(MyClass::getBlueId, MyClass::getRedId, MyClass::getGreenId))


如果需要其他评估顺序,请交换操作顺序:

extractors.stream()
    .flatMap(f -> fetchedElements.stream().map(item -> f.apply(item))
    .collect(Collectors.toSet()));

10-05 19:54