为什么Java中没有实例级的Stream.concat方法?

时间:2018-04-02 17:28:29

标签: java java-8 java-stream

我知道Stream.concat存在(doc)以连接两个流。但是,我遇到了需要在现有流中添加“更多”项目,然后继续处理它的情况。在这种情况下,我本来希望能够将以下方法联系起来:

getStream(someArg)
  .map(Arg::getFoo)
  .concat(someOtherStreamOfFoos) // Or append, or...
  .map(...)

但是,不存在此类实例级可链接append/concat方法。

这不是一个问题,要求解决这个问题,或更优雅的方法(虽然我当然会感激任何其他观点!)。相反,我问的是导致这一决定的设计因素。我信任,Stream界面是由一些非常聪明的人设计的,他们都知道Principle of Least Astonishment - 所以,我必须假设他们决定省略这个(对我来说)直观明显的方法,这意味着方法是反模式,或由于某些技术限制而无法实现。我很想知道原因。

2 个答案:

答案 0 :(得分:10)

我可以告诉你一个不起作用的原因。

Stream.concat定义为

static <T> Stream<T> concat(Stream<? extends T> a,
                            Stream<? extends T> b)

您可以concat Stream<HashMap>Stream<Map>加入Stream<Map>,甚至concatStream<HashMap>Stream<TreeMap>进入Stream<Map>。要使用实例方法执行此操作,您需要能够声明类似<U super T>的类型参数,而Java不允许这样做。

// It'd look kind of like this, if Java allowed it.
public <U super T> Stream<U> concat(Stream<? extends U> other)

Java只允许上限类型参数,而不是下限。

连接Stream<Something>Stream<SomethingElse>可能看似不寻常,但类型推断通常会产生类型参数,这些参数太具体,无法使用实例方法。例如,

Stream.concat(Stream.of(dog), animalStream)

如果写为

,则需要显式类型参数
Stream.<Animal>of(dog).concat(animalStream)

答案 1 :(得分:0)

我认为它只是错过了Stream API的功能。

请注意,RxJava的Observable具有所需功能的“concatWith”方法,因此您的问题是合理的:

Observable<String> o1 = ...;
Observable<Integer> o2 = ...;
o1.map(s -> s.length())
  .concatWith(o2)
  ....

如果当前的Optional为空,那么Java 8还有另外一个功能就是获得另一个可选项,如:

Optional.ofNullable(x).orElse(anotherOptional)

我想说的是你所描述的这个结论是可能的,只是没有在Stream中实现。