Java 8 Stream与集合存储

use*_*411 9 java memory collections java-8 java-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循环遍历集合,那么内存占用的区别是什么?

Stu*_*rks 25

关于流和存储的表态意味着甲流没有任何存储自身.如果流的源是一个集合,那么显然该集合具有存储来保存元素.

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

int sum = shapes.stream()
                .filter(s -> s.getColor() == BLUE)
                .mapToInt(s -> s.getWeight())
                .sum();
Run Code Online (Sandbox Code Playgroud)

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

这不是它的工作原理.没有临时的中间收藏.流操作是流水线操作的,因此从中filter传出的元素将被传递mapToInt并从而sum无需存储到集合中以及从集合中读取.

如果流源不是集合 - 比如,正在从网络集合中读取元素 - 则根本不需要任何存储.如下所示的管道:

int sum = streamShapesFromNetwork()
                .filter(s -> s.getColor() == BLUE)
                .mapToInt(s -> s.getWeight())
                .sum();
Run Code Online (Sandbox Code Playgroud)

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

  • @Coffemanz 当然,但是 `Stream.of` 是一个特例。它是一个 varargs 方法,因此传递给它的参数被收集到一个数组中,然后将其用作流的源。(所有可变参数方法都是通过将参数收集到数组中来工作的;这对流来说没有任何特殊之处。)现在考虑类似 `Stream<String> s2 = Stream.of("test", "test", "test ", "测试").map(String::toUpperCase);`。任何地方都没有包含四个“TEST”实例的集合或数组。大写值不会被存储,而是会延迟生成。 (2认同)

use*_*ica 7

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


Rak*_*esh 5

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

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

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

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

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

示例1:

List<String> employeeNameList = Arrays.asList("John","Peter","Sachin");
    Stream<String> s = employeeNameList.stream();

    // iterate through list
    s.forEach(System.out :: println);  // this work's perfectly fine
    s.forEach(System.out :: println);  // you will get IllegalStateException, stating stream already operated upon
Run Code Online (Sandbox Code Playgroud)

因此,您可以推断,集合可以根据需要迭代多次。但对于流来说,一旦你迭代,它就不会记住它应该做什么。所以,你需要再次指导它。

我希望,这是清楚的。