为什么java.util.Collection没有实现新的Stream接口?

我只是花了一些时间开始研究java-8关于流和lambda的嗡嗡声。令我惊讶的是,您无法直接在 .是否有技术原因导致接口未使用这些流操作的默认实现进行扩展?.map().filter()java.util.Collectionjava.util.Collection

谷歌搜索一下,我看到很多人们沿着以下模式编码的例子:

List<String> list = someListExpression;
List<String> anotherList = list.stream().map(x -> f(x)).collect(Collectors.toList());

这变得非常笨拙,如果你的代码中有很多这样的流操作。由于 和 与你想表达的内容完全无关,你宁愿说:.stream().collect()

List<String> list = someListExpression;
List<String> anotherList = list.map(x -> f(x));

答案 1

是的,这些决定有很好的理由:)

关键是急切操作和惰性操作之间的区别。您在第一个问题下给出的示例显示了预先执行的操作,其中映射或筛选列表会生成新列表。这没有错,但它通常不是你想要的,因为你经常做比你需要的更多的工作;预先操作必须对每个元素进行操作,并生成一个新集合。如果你正在编写多个操作(filter-map-reduce),那么你正在做很多额外的工作。另一方面,懒惰的操作组成得很好;如果您这样做:

Optional<Person> tallestGuy = people.stream()
                                    .filter(p -> p.getGender() == MALE)
                                    .max(comparing(Person::getHeight));

滤波器和减少(最大)操作融合在一起,形成一次通过。这是非常有效的。

那么,为什么不在 List 上公开 Stream 方法呢?好吧,我们像那样试过了。在许多其他原因中,我们发现混合懒惰的方法和渴望的方法会让用户感到困惑。通过将懒惰的方法分组到一个单独的抽象中,它变得更加清晰;上的方法就是那些使列表变异的方法;上的方法是对数据序列进行可组合、惰性操作的方法,而不管数据位于何处。filter()removeAll()ListStream

所以,如果你想做非常简单的事情,你建议的方式是很好的,但是当你试图在它的基础上构建时,它开始分崩离析。额外的方法很烦人吗?确定。但是,将数据结构(主要关于在内存中组织数据)和流(主要关于组合聚合行为)的抽象分开,可以更好地扩展到更复杂的操作。stream()

对于第二个问题,您可以相对轻松地执行此操作:实现如方法:

public<U> Stream<U> map(Function<T,U> mapper) { return convertToStream().map(mapper); }

但那只是逆流而上。最好只是实现一个有效的 stream() 方法。


答案 2