gpt4 book ai didi

java - 在 Lambda java 8 中改变实例或局部对象变量

转载 作者:太空狗 更新时间:2023-10-29 22:45:34 25 4
gpt4 key购买 nike

我知道出于并发原因,我无法在 Java 8 的 lambda 中更新局部变量的值。所以这是非法的:

double d = 0;
orders.forEach( (o) -> {
d+= o.getTotal();
});

但是,如何更新实例变量或更改局部对象的状态呢?例如,我有一个 Swing 应用程序,我有一个按钮和一个声明为实例变量的标签,当我单击按钮时,我想隐藏标签

 jButton1.addActionListener((  e) -> {
jLabel.setVisible(false);
});

我没有遇到编译器错误并且工作正常,但是......在 lambda 中更改对象的状态是否正确?我将来会遇到并发问题或其他问题吗?

这里是另一个例子。想象下面的代码在一个servlet的doGet方法中我会在这里遇到问题吗?如果答案是肯定的:为什么?

String key = request.getParameter("key");

Map<String, String> resultMap = new HashMap<>();

Map<String, String> map = new HashMap<>();
//Load map

map.forEach((k, v) -> {
if (k.equals(key)) {
resultMap.put(k, v);
}
});
response.getWriter().print(resultMap);

我想知道的是:什么时候在 lambda 中改变对象实例的状态是正确的?

最佳答案

您的假设不正确。

您只能更改 lambda 中的effectively final 变量,因为 lambda 是匿名内部类的语法糖*。
*它们实际上不仅仅是语法糖,但这与这里无关。

并且在匿名内部类中,您只能更改有效的最终变量,因此这同样适用于 lambda。

只要编译器允许,您就可以使用 lambda 做任何您想做的事情,现在进入行为部分:

  • 如果您在并行设置中修改依赖于其他状态的状态,那么您就有麻烦了。
  • 如果您在线性设置中修改依赖于其他状态的状态,那么一切都很好。
  • 如果您修改不依赖于任何其他任何东西的状态,那么一切都很好。

一些例子:

class MutableNonSafeInt {
private int i = 0;

public void increase() {
i++;
}

public int get() {
return i;
}
}

MutableNonSafeInt integer = new MutableNonSafeInt();
IntStream.range(0, 1000000)
.forEach(i -> integer.increase());
System.out.println(integer.get());

无论发生什么,这都会按预期打印 1000000,即使它取决于之前的状态。

现在让我们并行化流:

MutableNonSafeInt integer = new MutableNonSafeInt();
IntStream.range(0, 1000000)
.parallel()
.forEach(i -> integer.increase());
System.out.println(integer.get());

现在它打印不同的整数,例如 199205 或 249165,因为其他线程并不总是看到不同线程所做的更改,因为没有同步。

但是假设我们现在摆脱我们的虚拟类并使用AtomicInteger,它是线程安全的,我们得到以下结果:

AtomicInteger integer = new AtomicInteger(0);
IntStream.range(0, 1000000)
.parallel()
.forEach(i -> integer.getAndIncrement());
System.out.println(integer.get());

现在它再次正确打印 1000000。
然而,同步的成本很高,我们在这里几乎失去了并行化的所有好处。

关于java - 在 Lambda java 8 中改变实例或局部对象变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22598665/

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