标准集合返回的Stream实现有多专业?

时间:2015-02-16 16:39:09

标签: java java-8 java-stream

Stream是一个接口,因此每当有人抓住Stream对象时,就会隐藏许多特定于实现的细节。

例如,请使用以下代码:

List<String> list = new ArrayList<>();
...
int size = list.stream()
               .count();

它是以恒定还是线性时间运行?或者这个:

Set<String> set = new TreeSet<>();
...
set.stream()
   .sorted()
   .forEach(System.out::println);

那是O(n)还是O(n log n)?

一般来说,标准集合返回的流实现有多专业化?

2 个答案:

答案 0 :(得分:15)

  

它是在恒定时间还是线性时间运行?

当前实现以线性时间运行:

public final long count() {
    return mapToLong(e -> 1L).sum();
}

但是,在某些情况下可以在某些情况下以恒定时间运行,这可以得到改善(这是某个地方的RFE)。

如何?流由流源描述,零个或多个中间操作终端操作(此处,count()是终端操作)。流实现维护有关源的一组特征,并知道操作如何修改特征。例如,由Collection支持的流具有特征SIZED,而由Iterator支持的流的大小不是。类似地,操作map()是大小保留的,但操作filter()破坏了任何大小的先验知识。流实现在启动终端操作之前知道管道的组合特征,因此它知道源是否大小以及是否所有阶段都是大小保留的,并且在这种情况下,可以简单地询问源的大小并绕过所有实际的流计算。 (但是Java 8中的实现不会发生这种情况。)

请注意,流不需要专门用于支持这一点; Collection类使用知道其特性的Spliterator创建流,因此不需要专门的集合实现,只需更新共享实现以利用这些特定信息。

答案 1 :(得分:2)

sorted()方法不会改变大小,因此从理论上讲,未来的实现可能会在stream().sorted().count()时间内执行O(1)链。

https://github.com/speedment/speedment查看Stream接口的[speedment]开源实现。这些流可以内省自己的管道并优化流中的一个或几个步骤。