如何在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++;
}
为了练习Stream,我尝试将其重写为Stream
:
map.entrySet().stream() .forEach(e -> item[index++].setImage(e.getValue().getImage()));
导致我的错误:
错误:从lambda表达式引用的局部变量必须是final或有效的final
如何重写要在其中使用的Stream
递增变量index
?
回答:
你不应该 两者看起来很相似,但是在概念上是不同的。循环只是一个循环,但是一条forEach
指令指示库对每个元素执行操作,
而不指定操作顺序(对于并行流)或 执行该操作的 线程 。如果使用forEachOrdered
,则 仍然不能保证线程,
但是至少可以保证后续元素上的动作之间发生事前关系。
特别注意文档说:
对于任何给定的元素,可以在库选择的任何时间和线程中执行操作。如果操作访问共享状态,则它负责提供所需的同步。
但是,正如@Marko在下面的注释中指出的那样,即使措辞有些混乱,它也仅适用于并行流。但是,使用循环意味着您甚至不必担心所有这些复杂的事情!
因此,最重要的是:如果该逻辑是其所在函数的一部分,则使用循环;如果forEach
您只想告诉Java对流的元素“执行此操作”,则使用循环。
那是关于forEach
vs循环。现在讨论为什么变量首先需要为final,以及为什么可以对字段和数组元素进行分类的主题。就像它说的那样,这是因为Java有一个局限性,除非匿名类和lambda永远不会更改,否则它无法访问局部变量。这意味着不仅他们自己不能更改它,而且您也不能在他们外部更改它。但这仅适用于局部变量,这就是为什么它适用于其他所有类(例如类字段或数组元素)的原因。
我认为,这种限制的原因是生命周期问题。局部变量仅在包含它的块正在执行时存在。归功于垃圾回收,其他所有东西都存在,同时有对其的引用。而且所有其他内容还包括lambda和匿名类,因此,如果它们可以修改具有不同生存期的局部变量,则可能导致类似于C
++中悬挂引用的问题。因此,Java采取了简单的方法:它只在创建lambda
/匿名类时复制本地变量。但是,如果您可以更改该变量,则会导致混乱(因为副本不会更改,并且由于副本是不可见的,因此非常混乱)。因此,Java只是禁止对此类变量进行任何更改,仅此而已。
关于最终变量和匿名类,已经讨论了很多问题,例如这个。
以上是 如何在Java Stream中增加值? 的全部内容, 来源链接: utcz.com/qa/419503.html