为什么 Stream.flatMap 不能接收一个集合?

11

假设以下是数据类的示例:

class Country {

    List<Region> regions = new ArrayList<>();

    List<Region> getRegions() {
        return regions;
    }

}

class Region {

    String getName() {
        return "some name";
    }

}

假设我有一个国家列表

    List<Country> countries = new ArrayList<>();

我想将它们流式传输到它们所在的区域和相应的名称,我想要做以下操作:

    countries.stream().flatMap(Country::getRegions).map(Region::getName)...

然而,该代码无法编译,因为 "getRegions" 的返回值是一个集合(列表),而不是流,而 flatMap 方法接受的是流。但是,由于我知道任何集合都可以通过其 Collection.stream() 方法转换成流,所以这不应该是个问题。尽管如此,我还是被迫按照以下方式编写它:

    countries.stream().flatMap(c -> c.getRegions().stream()).map(Region::getName)...

如果考虑到更丰富的上下文,这种写法比前者不易阅读。

问题是我是否忽略了任何原因导致这样冗长?我们的框架中有很多例子都强制我采用这种写法,总是让我感到不满意。也许我只需要在项目中添加Kotlin,并扩展Stream类与一个接收Collection参数的flatMap方法 :p


我也尝试了以下代码,因为在我的脑海中它很有意义,但显然它无法编译: Country::getRegions::stream - Lukas
2
我同意 flatMap 应该接受一个集合,但我不确定 SO 能否提供一个明确的解释,除了“编写它的人没有以那种方式编写它”。 - khelwood
无法翻译,"no"可以作为答案 :) - Lukas
请检查Collectors.groupingBy是否对您有帮助。一些示例可在以下网址找到:https://www.mkyong.com/java8/java-8-collectors-groupingby-and-mapping-example/ - Raffael Bechara Rameh
3
你可以从该方法中返回一个Stream<Country>,或者添加一个名为regions的方法来实现。 - Jorn Vernee
4
你仍然可以使用.map(Country::getRegions).flatMap(List::stream),但我不明白为什么方法引用被认为比简单的lambda表达式更优越... - Holger
1个回答

18

这可能是一个技术上的原因,虽然不太理想但可能是为什么没有这样做的原因。在Java中不能对通用类型进行重载。

他们需要支持

 Stream.flatMap(Function<Object, Stream<X>> function)

这意味着他们不能过度使用它

 Stream.flatMap(Function<Object, Collection<X>> function)

由于这两种方法在擦除后具有相同的签名。

他们可以添加一个方法。

 Stream.flatMapCollection(Function<Object, Collection<X>> function)
或者
 Stream.flatMapIterable(Function<Object, Iterable<X>> function)

 Stream.flatMapI(Function<Object, Iterable<X>> function)

但那不会漂亮。


是的,如果添加了那些方法,它将会有所改进。 - khelwood
2
@khelwood 可能不会更短。理想情况下,他们应该为稀疏类型和泛型重载添加支持。 - Peter Lawrey
1
那个答案其实很令人满意。或者说它提供了一个有效的解释。谢谢 - Lukas
flatCollectionflatArray提供在StreamEx中。 - 123-xyz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接