Pat*_*tan 86 java lambda java-8
修改局部变量forEach
会产生编译错误:
正常
int ordinal = 0;
for (Example s : list) {
s.setOrdinal(ordinal);
ordinal++;
}
Run Code Online (Sandbox Code Playgroud)
随着Lambda
int ordinal = 0;
list.forEach(s -> {
s.setOrdinal(ordinal);
ordinal++;
});
Run Code Online (Sandbox Code Playgroud)
知道如何解决这个问题吗?
Oli*_*ire 135
使用Java 8+:
AtomicInteger ordinal = new AtomicInteger(0);
list.forEach(s -> {
s.setOrdinal(ordinal.getAndIncrement());
});
Run Code Online (Sandbox Code Playgroud)
使用Java 10+:
int[] ordinal = { 0 };
list.forEach(s -> {
s.setOrdinal(ordinal[0]++);
});
Run Code Online (Sandbox Code Playgroud)
Stu*_*rks 12
这非常接近XY问题.也就是说,被问到的问题本质上是如何从lambda变异捕获的局部变量.但是手头的实际任务是如何对列表的元素进行编号.
根据我的经验,在80%的时间内存在如何从lambda内变异捕获的局部的问题,有更好的方法可以继续.通常这涉及到减少,但在这种情况下,在列表索引上运行流的技术很适用:
IntStream.range(0, list.size())
.forEach(i -> list.get(i).setOrdinal(i));
Run Code Online (Sandbox Code Playgroud)
new*_*cct 11
如果你只需要将值从外部传递给lambda,而不是将它取出,你可以使用常规的匿名类而不是lambda来实现:
list.forEach(new Consumer<Example>() {
int ordinal = 0;
public void accept(Example s) {
s.setOrdinal(ordinal);
ordinal++;
}
});
Run Code Online (Sandbox Code Playgroud)
由于来自lamda外部的已使用变量必须(隐式)最终,您必须使用类似的东西AtomicInteger
或编写自己的数据结构.
请参阅 https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html#accessing-local-variables.
另一种方法AtomicInteger
是使用数组(或任何其他能够存储值的对象):
final int ordinal[] = new int[] { 0 };
list.forEach ( s -> s.setOrdinal ( ordinal[ 0 ]++ ) );
Run Code Online (Sandbox Code Playgroud)
但是请参阅Stuart 的回答:可能有更好的方法来处理您的案例。
归档时间: |
|
查看次数: |
76902 次 |
最近记录: |