【问题标题】:Why is there no flatten() method in the Stream API?为什么 Stream API 中没有 flatten() 方法?
【发布时间】:2017-07-15 09:21:08
【问题描述】:

以下两个代码 sn-ps 产生相同的结果。

flatMap:

Stream.iterate(2, n -> n + 4)
            .flatMap(n -> Stream.of(n, -(n + 2)));

使用map 后跟flatMap 使用identity

Stream.iterate(2, n -> n + 4)
            .map(n -> Stream.of(n, -(n + 2)))
            .flatMap(Function.identity());

因此在Stream 接口中包含一个无参数的flatten 方法似乎很自然(就像在Scala 的Stream 中一样),以允许将前面的示例写成:

Stream.iterate(2, n -> n + 4)
            .map(n -> Stream.of(n, -(n + 2)))
            .flatten();

那么为什么Stream API 中没有flatten() 方法呢?

【问题讨论】:

  • API 已经相当臃肿。这将是不必要的添加。
  • 我认为这个问题没有抓住重点。基本的 API 设计说只投入很少的东西就可以实现您想要实现的目标。并且有可能,没有理由使用 flatten() 方法。想象一下,将每个可能的用例都作为 API 中的专用方法。它很快就会变得臃肿。
  • 我不认为 API 膨胀是一个有效的观点。正如我在问题中提到的那样,Scala 中有flatten(也有flatMap)。我什至可以转而说,好吧,如果问题可以通过结合mapflatten 来解决,那为什么还要包括flatMap。当然,flatMap 存在的原因是性能和便利性。这是简约 API 和便捷 API 之间的权衡。

标签: java-8 java-stream


【解决方案1】:

无法在 Java 中实现 flatten 方法。它只能在 Stream<? extends Stream<?>> 上调用,但无法确定 T extends Stream<R> 是否适用于某些类型 R

如果你看一下 Scala 中的方法签名:

def flatten[B](implicit asTraversable: (A) ⇒ GenTraversableOnce[B]): Stream[B]

它实际上接受了一个隐含的证据参数,即 A 类型是某个类型 B 的集合。

Java 中的flatMap 方法接受一个函数T -> Stream<? extends R>

<R> Stream<R> flatMap(Function<? super T,? extends Stream<? extends R>> mapper)

所以我们知道它可以展平为Stream&lt;R&gt;

flatten 的静态实现是可能的:

static <R> Stream<R> flatten(Stream<? extends Stream<? extends R>> stream) {
    return stream.flatMap(Function.identity());
}

【讨论】:

    猜你喜欢
    • 2015-05-01
    • 2015-12-31
    • 1970-01-01
    • 1970-01-01
    • 2021-05-17
    • 2016-11-18
    • 2015-09-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多