gpt4 book ai didi

java - 如何在 Java Stream 中增加一个值?

转载 作者:塔克拉玛干 更新时间:2023-11-01 22:07:03 26 4
gpt4 key购买 nike

我想在每次迭代中将 index 的值增加 1。在for-loop中很容易实现。变量 imageImageView 的数组。

这是我的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()));

导致我的错误:

error: local variables referenced from a lambda expression must be final or effectively final

如何重写 Stream 递增要在其中使用的变量 index

最佳答案

你不应该。这两个看起来很相似,但它们在概念上是不同的。循环只是一个循环,但是 forEach 指示库对每个元素执行操作,既没有指定操作顺序(对于并行流)也没有指定执行它们的线程。如果您使用 forEachOrdered,那么仍然无法保证线程,但至少您可以保证后续元素上的操作之间存在先行关系。

特别注意 the docs说:

For any given element, the action may be performed at whatever time and in whatever thread the library chooses. If the action accesses shared state, it is responsible for providing the required synchronization.

正如@Marko 在下面的评论中指出的那样,它只适用于并行流,即使措辞有点困惑。然而,使用循环意味着您甚至不必担心所有这些复杂的事情!

所以底线是:如果该逻辑是它所在函数的一部分,请使用循环,如果您只想告诉 Java 对其中的元素“做这个做那个”,请使用 forEach流。

那是关于 forEach 与循环的对比。现在讨论为什么变量首先需要是最终的,以及为什么可以对类字段和数组元素这样做。这是因为,就像它说的那样,Java 有一个限制,即匿名类和 lambda 不能访问局部变量,除非它永远不会改变。这意味着不仅他们自己无法更改它,而且您也无法在他们之外更改它。但这仅适用于局部变量,这就是为什么它适用于类字段或数组元素等其他所有内容。

我认为造成这种限制的原因是生命周期问题。局部变量仅在包含它的 block 正在执行时存在。多亏了垃圾收集,其他一切都存在,但有对它的引用。并且其他所有内容也包括 lambda 和匿名类,因此如果它们可以修改具有不同生命周期的局部变量,那可能会导致类似于 C++ 中的悬空引用的问题。所以 Java 采取了简单的方法:它只是在创建 lambda/匿名类时复制局部变量。但是,如果您可以更改该变量,那将导致困惑(因为副本不会更改,并且由于副本是不可见的,所以会非常困惑)。所以 Java 只是禁止对此类变量进行任何更改,仅此而已。

关于最终变量和匿名类的问题已经讨论过很多,比如 this one .

关于java - 如何在 Java Stream 中增加一个值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40304842/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com