加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

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

发布时间:2020-12-15 04:36:31 所属栏目:Java 来源:网络整理
导读:我希望将每次迭代的索引值增加1.在for循环中很容易实现.变量图像是 ImageView的数组. 这是我的for循环. for (Map.EntryString,Item entry : map.entrySet()) { image[index].setImage(entry.getValue().getImage()); index++;} 为了练习Stream,我尝试将其重
我希望将每次迭代的索引值增加1.在for循环中很容易实现.变量图像是 ImageView的数组.

这是我的for循环.

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递增要使用的变量索引?

解决方法

你不应该.这两个看起来很相似,但它们在概念上是不同的.循环只是一个循环,但是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 vs循环.现在讨论为什么变量首先需要最终的主题,以及为什么你可以对类字段和数组元素这样做.这是因为,就像它说的那样,Java有一个限制,即匿名类和lambdas不能访问局部变量,除非它永远不会改变.意思不仅是他们自己不能改变它,而且你也不能在它们之外改变它.但这只适用于局部变量,这就是为什么它适用于其他一切,如类字段或数组元素.

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

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

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读