Nik*_*las 4 java dictionary java-8 java-stream
我想增加index每次迭代的值1.很容易实现for-loop.变量image是一个数组ImageView.
这是我的for-loop.
for (Map.Entry<String, Item> entry : map.entrySet()) {
image[index].setImage(entry.getValue().getImage());
index++;
}
Run Code Online (Sandbox Code Playgroud)
为了练习Stream,我尝试将其重写为Stream:
map.entrySet().stream()
.forEach(e -> item[index++].setImage(e.getValue().getImage()));
Run Code Online (Sandbox Code Playgroud)
导致我错误的原因:
错误:从lambda表达式引用的局部变量必须是final或者有效的final
如何重写Stream递增index要使用的变量?
你不应该.这两个看起来很相似,但它们在概念上是不同的.循环只是一个循环,但是forEach指示库对每个元素执行操作,而不指定操作的顺序(对于并行流),也不指定将执行它们的线程.如果您使用forEachOrdered,那么仍然无法保证线程,但至少您可以保证在后续元素上的操作之间发生关系.
特别注意文档说:
对于任何给定元素,可以在任何时间以及库选择的任何线程中执行该动作.如果操作访问共享状态,则它负责提供所需的同步.
正如@Marko在下面的评论中指出的那样,它只适用于并行流,即使措辞有点令人困惑.然而,使用循环意味着您甚至不必担心所有这些复杂的东西!
所以底线是:如果逻辑是它所在函数的一部分,则使用循环,forEach如果你只想告诉Java"对流的元素执行此操作",则使用循环.
这是关于forEachvs循环.现在讨论为什么变量首先需要最终的主题,以及为什么你可以对类字段和数组元素这样做.这是因为,就像它说的那样,Java有一个限制,即匿名类和lambdas不能访问局部变量,除非它永远不会改变.意思不仅是他们自己不能改变它,而且你也不能在它们之外改变它.但这只适用于局部变量,这就是为什么它适用于其他一切,如类字段或数组元素.
我认为,这种限制的原因是终身问题.只有在包含它的块正在执行时,才存在局部变量.由于垃圾收集,所以在存在引用的同时存在其他所有内容.其他一切都包括lambdas和匿名类,所以如果他们可以修改具有不同生命周期的局部变量,那么可能会导致类似于C++中悬空引用的问题.所以Java采取了简单的方法:它只是在创建lambda/anonymous类时复制局部变量.但如果您可以更改该变量,那将导致混淆(因为副本不会更改,并且由于副本不可见,因此会非常混乱).所以Java只是禁止对这些变量进行任何更改,就是这样.
关于最终变量和已经讨论过的匿名类有很多问题,比如这个.
| 归档时间: |
|
| 查看次数: |
6580 次 |
| 最近记录: |