Java 8 Stream与集合存储

我一直在阅读Java 8 Streams以及从数据源流式传输数据的方式,而不是让整个集合从中提取数据。

特别是我引用了一篇关于Java 8中的流的文章。

“没有存储。流没有值存储;它们通过一系列计算步骤从源(可能是数据结构,生成函数,I / O通道等)传输值。” 来自: http//www.drdobbs.com/jvm/lambdas-and-streams-in-java-8-libraries/240166818?pgno = 1

我理解从一个源一步一步地流式传输数据的概念。 我不明白的是,如果你是从一个集合流式传输,怎么没有存储? 该集合已存在于Heap中,您只是从该集合中流式传输数据,该集合已存在于“存储”中。

如果我只是通过标准for循环遍历集合,那么内存占用的区别是什么?

关于流和存储的声明意味着流没有自己的任何存储。 如果流的源是一个集合,那么显然该集合具有存储来保存元素。

我们来看看那篇文章中的一个例子:

int sum = shapes.stream() .filter(s -> s.getColor() == BLUE) .mapToInt(s -> s.getWeight()) .sum(); 

假设shapes是一个拥有数百万个元素的Collection 。 可以想象, filter操作将迭代源中的元素并创建临时的结果集合,这些结果也可能包含数百万个元素。 然后mapToInt操作可以迭代该临时集合并生成其求和结果。

这不是它的工作原理。 没有临时的中间收集。 流操作是流水线操作的,因此从filter中出现的元素将通过mapToInt传递给sum而不会存储到集合中并从中读取。

如果流源不是集合 – 比如,正在从网络集合中读取元素 – 则根本不需要任何存储。 像下面这样的管道:

 int sum = streamShapesFromNetwork() .filter(s -> s.getColor() == BLUE) .mapToInt(s -> s.getWeight()) .sum(); 

可能会处理数百万个元素,但它不需要在任何地方存储数百万个元素。

将流视为连接到水箱的喷嘴,这是您的数据结构。 喷嘴没有自己的存储空间。 当然,流提供的水(数据)来自具有存储的源,但流本身没有存储。 将另一个喷嘴(流)连接到您的储jar(数据结构)将不需要存储全新的数据副本。

流只是数据的视图 ,它没有自己的存储,您无法通过流修改底层集合(假设它是构建在集合顶部的流)。 这就像是“只读”访问。

如果您有任何RDBMS经验 – 它与“视图”完全相同。

  1. 集合是一种数据结构。 根据问题,您可以决定使用哪个集合,如ArrayList,LinekedList(考虑时间和空间复杂度)。 Stream只是一种处理工具,让您的生活更轻松。

  2. 其他不同之处在于,您可以将Collection视为内存中的数据结构,您可以在其中添加,删除元素。 在Stream中,您可以执行两种操作:

    一个。 中间操作 :对结果集进行过滤,映射,排序和限制
    终端操作 :forEach,将结果集收集到集合中。

    但是如果您注意到,使用流您无法添加或删除元素。

  3. Stream是一种迭代器 ,你可以通过流遍历集合。 注意,你只能遍历一次流,让我举个例子来更好地理解:

例1:

 List employeeNameList = Arrays.asList("John","Peter","Sachin"); Stream s = employeeNameList.stream(); // iterate through list s.dorEach(System.out :: println); // this work's perfectly fine s.dorEach(System.out :: println); // you will get IllegalStateException, stating stream already operated upon 

所以,您可以推断出,您可以根据需要迭代多次。 但对于流,一旦你迭代,它将不记得它应该做什么。 所以,你需要再次指导它。

我希望,很清楚。