java - Java8容器`for each`和Stream`for each`有什么区别
问题描述
我知道我们可以List.foreach
用来遍历,我们也可以List.stream.foreach
用来遍历。我不明白在 Java8 中遍历哪个更好。
解决方案
该forEach(Consumer)
方法在Iterable
接口中声明Collection
,因此List
扩展。默认实现forEach(Consumer)
是:
default void forEach(Consumer<? super T> action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}
如您所见,默认实现只是action
在 for-each 循环中调用。for-each 循环只是语法糖:
for (Iterator<?> iterator = iterable.iterator(); iterator.hasNext(); ) {
Object element = iterator.next();
// Do what you need to with element
}
Iterator
除非您在 for-each 循环中无权访问。
的特定实现Iterable
可能会改变它实际迭代其元素的方式(它可能使用也可能不使用 an Iterator
),但它几乎总是归结为 some for
orwhile
循环。我说“几乎总是”是因为可能涉及某种类型的递归或链接。
现在,当您只是尝试按顺序迭代时, usingList.stream().forEach(Consumer)
会创建一个不必要的对象。如果您确实需要以管道方式处理元素集合(例如映射、过滤、更多映射等),则应仅使用流 API。Stream
List
因此,对于简单的迭代,几乎在所有情况下,使用List.stream().forEach(Consumer)
的性能都比简单的调用低。List.forEach(Consumer)
性能提升很可能可以忽略不计,但“优化”并不过分是一个足够简单的修复;特别是如果您一开始就没有犯“错误”。如果您不需要它们,请不要创建对象。
最好简单地使用 for-each 循环而不是forEach(Consumer)
虽然。它比功能更强大的对应物更容易阅读。
编辑
正如 Holger 在评论中提到的,与以下Stream.forEach(Consumer)
有很大的不同Iterable.forEach(Consumer)
:它不保证元素的相遇顺序。虽然接口的迭代顺序Iterable.forEach(Consumer)
也没有定义Iterable
,但可以通过扩展接口(如List
)来定义。但是,在使用时,无论 的来源如何,都Stream
不能保证顺序。Stream
如果您希望在使用 a 时保证订单,Stream
您必须使用Stream.forEachOrdered(Consumer)
.
推荐阅读
- c# - SQL Server 在结果中返回无效(unicode/hexidecimal)字符
- r - 填写 dbplyr 中的缺失值
- python - Pandas:如何在不添加额外列的情况下“合并”两行交替 NaN 的内容?
- angular - Angular 无法导航到其他组件
- c# - 从脚本引用的布尔不更新?
- visual-studio - 在 Visual Studio 合并工具中将搁置集、本地和结果对齐
- sql - 将运行总计 oracle sql 查询转换为最终总计
- python - 创建多个异步请求
- bash - Shell:单个变量中的多个参数
- python - 将 Dataframe 拆分为带有 n 个元组 Pandas 的 zip 对象