2017-07-15 16 views
2

以下两个代码片段会产生相同的结果。Stream API中为什么没有flatten()方法?

随着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()方法?

+3

的API已经相当臃肿。这将是一个不必要的补充。 – 4castle

+3

我认为这个问题忽略了一点。基本的API设计说尽可能少地实现你想达到的目标。如果可能的话,flatten()方法没有任何理由。试想一下,将所有可能的用例作为API中的专用方法。它会很快膨胀。 – loonytune

+1

我不认为API膨胀是一个有效的观点。正如我在问题中提到的那样,Scala中有'flatten'(它也有'flatMap')。我甚至可以改变论点并说,好吧,如果问题可以通过结合'map'和'flatten'来解决,为什么还要包含'flatMap'。当然,为什么'flatMap'存在的原因是性能和方便。这是简约API和便捷API之间的折衷。 –

回答

5

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

如果你看一下方法签名斯卡拉:

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

它其实需要一个隐含的证据参数类型A是某种类型B的集合。

flatMap方法在Java中需要一个功能T -> Stream<? extends R>

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

所以我们知道,它可以被夷为平地,Stream<R>

静态实施flatten是可能的:

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