当我们从集合列表中获取 Stream 时,幕后到底发生了什么?我发现很多博客都说Stream不存储任何数据。如果这是真的,请考虑代码片段:
List<Integer> list = new ArrayList<Integer>();
list.add(1);
list.add(2);
list.add(3);
Stream<Integer> stream = list.stream();
list = null;
stream.forEach(i -> System.out.print(i));
正如我们所见,即使 List(源)为 null
,元素也可以流式访问。
这怎么可能?
最佳答案
Stream API 不知道 List
里面有什么。直到对第一个和剩余元素执行 lambda 表达式。
stream.forEach(i -> System.out.print(i));
上面的代码只不过是以下内容的快捷方式:
stream.forEach(new Consumer<String>() {
@Override
public void accept(String t) {
System.out.println(t);
}
});
lambda 表达式只是一个实现的接口(interface),即只有且只有一个方法的函数式接口(interface)。这个特殊的接口(interface)被注释为 @FunctionalInterface
并且可以表示为 lambda 表达式。
重点是,方法accept(String t)
在实际调用之前不会执行 - lambda 也会发生同样的情况。考虑以下因素:
Consumer<String> consumer = i -> System.out.print(i);
// At this point the method `System.out.print(i)` remains not executed.
// Whatever expensive operation inside any lambda remains unexecuted
// until its only method is called
stream.forEach(consumer); // Now it encounters all the elements
因此,Stream 不知道元素,因为它将整个执行留给传递的 lambda 表达式。
<小时/>顺便设置list = null
自 Stream<Integer>
起不影响任何事情已经被创建了。源存储为 Spliterator<T>
在 AbstractPipeline
(line 123) 。
关于Java 流 API,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51712988/