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经验 – 它与“视图”完全相同。
-
集合是一种数据结构。 根据问题,您可以决定使用哪个集合,如ArrayList,LinekedList(考虑时间和空间复杂度)。 Stream只是一种处理工具,让您的生活更轻松。
-
其他不同之处在于,您可以将Collection视为内存中的数据结构,您可以在其中添加,删除元素。 在Stream中,您可以执行两种操作:
一个。 中间操作 :对结果集进行过滤,映射,排序和限制
湾 终端操作 :forEach,将结果集收集到集合中。但是如果您注意到,使用流您无法添加或删除元素。
-
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
所以,您可以推断出,您可以根据需要迭代多次。 但对于流,一旦你迭代,它将不记得它应该做什么。 所以,你需要再次指导它。
我希望,很清楚。