如何在Java Stream中增加值? [英] How to increment a value in Java Stream?

查看:693
本文介绍了如何在Java Stream中增加值?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想增加 index 的值,每次迭代按 1 。很容易在 for-loop 中实现。变量 image 是一个 ImageView 的数组。

I want to increment value of index with the each iteration by 1. Easily to be achieved in the for-loop. The variable image is an array of ImageView.

这是我的 for-loop

for (Map.Entry<String, Item> entry : map.entrySet()) {      
    image[index].setImage(entry.getValue().getImage());
    index++;
}

为了练习Stream,我试图将其重写为

In order to practise Stream, I have tried to rewrite it to the Stream:

map.entrySet().stream()
    .forEach(e -> item[index++].setImage(e.getValue().getImage()));

导致错误:


错误:从lambda表达式引用的局部变量必须是最终的或有效的最终

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

如何重写 Stream 递增变量 index 以用于?

How to rewrite the Stream incrementing the variable index to be used in?

推荐答案

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

You shouldn't. These two look similar, but they are conceptually different. The loop is just a loop, but a forEach instructs the library to perform the action on each element, without specifying neither the order of actions (for parallel streams) nor threads which will execute them. If you use forEachOrdered, then there are still no guarantees about threads, but at least you have the guarantee of happens-before relationship between actions on subsequent elements.

特别注意文档说:


对于任何给定元素,可以在
和库选择的任何线程中的任何时间执行操作。如果操作访问
共享状态,则它负责提供所需的
同步。

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.

As @Marko但是,在下面的评论中指出,它只适用于并行流,即使措辞有点令人困惑。然而,使用循环意味着你甚至不必担心所有这些复杂的东西!

As @Marko noted in the comments below, though, it only applies to parallel streams, even if the wording is a bit confusing. Nevertheless, using a loop means that you don't even have to worry about all this complicated stuff!

所以底线是:如果逻辑是一个部分则使用循环它所使用的函数,并使用 forEach ,如果你只想告诉Java对流的元素执行此操作。

So the bottom line is: use loops if that logic is a part of the function it's in, and use forEach if you just want to tell Java to "do this and that" to elements of the stream.

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

That was about forEach vs loops. Now on the topic of why the variable needs to be final in the first place, and why you can do that to class fields and array elements. It's because, like it says, Java has the limitation that anonymous classes and lambdas can't access a local variable unless it never changes. Meaning not only they can't change it themselves, but you can't change it outside them as well. But that only applies to local variables, which is why it works for everything else like class fields or array elements.

我认为,这种限制的原因是生命周期问题。仅当包含它的块正在执行时,才存在局部变量。由于垃圾收集,所有其他东西都存在,而有引用它。其他一切都包括lambdas和匿名类,所以如果他们可以修改具有不同生命周期的局部变量,那么可能会导致类似于C ++中悬空引用的问题。所以Java采取了简单的方法:它只是在创建lambda / anonymous类时复制局部变量。但如果你可以改变那个变量,那会导致混乱(因为副本不会改变,因为副本是不可见的,所以会非常混乱)。所以Java只是禁止对这些变量进行任何更改,就是这样。

The reason for this limitation, I think, is lifetime issues. A local variable exists only while the block containing it is executing. Everything else exists while there are references to it, thanks to garbage collection. And that everything else includes lambdas and anonymous classes too, so if they could modify local variables which have different lifetime, that could lead to problems similar to dangling references in C++. So Java took the easy way out: it simply copies the local variable at the time the lambda / anonymous class is created. But that would lead to confusion if you could change that variable (because the copy wouldn't change, and since the copy is invisible it would be very confusing). So Java just forbids any changes to such variables, and that's that.

关于最终变量和已经讨论过的匿名类,有很多问题,比如这个

There are many questions on the final variables and anonymous classes discussed already, like this one.

这篇关于如何在Java Stream中增加值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆