如何在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对流的元素“执行此操作”,则使用循环。

那是关于forEachvs循环。现在讨论为什么变量首先需要为final,以及为什么可以对字段和数组元素进行分类的主题。就像它说的那样,这是因为Java有一个局限性,除非匿名类和lambda永远不会更改,否则它无法访问局部变量。这意味着不仅他们自己不能更改它,而且您也不能在他们外部更改它。但这仅适用于局部变量,这就是为什么它适用于其他所有类(例如类字段或数组元素)的原因。

我认为,这种限制的原因是生命周期问题。局部变量仅在包含它的块正在执行时存在。归功于垃圾回收,其他所有东西都存在,同时有对其的引用。而且所有其他内容还包括lambda和匿名类,因此,如果它们可以修改具有不同生存期的局部变量,则可能导致类似于C

++中悬挂引用的问题。因此,Java采取了简单的方法:它只在创建lambda

/匿名类时复制本地变量。但是,如果您可以更改该变量,则会导致混乱(因为副本不会更改,并且由于副本是不可见的,因此非常混乱)。因此,Java只是禁止对此类变量进行任何更改,仅此而已。

关于最终变量和匿名类,已经讨论了很多问题,例如这个。

以上是 如何在Java Stream中增加值? 的全部内容, 来源链接: utcz.com/qa/419503.html

回到顶部