java stream.foreach 中的 8 个局部变量
java 8 local variable in stream.foreach
我想在 lambda 函数中使用局部变量,但出现错误:
请参阅代码中的 1. 和 2. 点。
class Foo {
int d = 0; // 1. It compiles, but ugly, 2. doesnt compile
public void findMax(List<List<Route>> routeLists) {
int d = 0; // 2.Error : Local variable dd defined in an enclosing scope must be final or effectively final
routeLists.forEach(e-> {
e.forEach(ee -> {
d+=ee.getDistance();
});
});
... doing some other operation with d
}
}
如何在不将它们设置为全局变量的情况下使用它们?
您不能将 int 用作变量,因为它必须是最终的才能在流中使用。
但是您可以创建一个 class 包装 int。
然后将持有这个class的变量声明为final。
正在更改内部 int 变量的内容。
public void findMax(List<List<Route>> routeLists) {
final IntWrapper dWrapper = new IntWrapper();
routeLists.forEach(e-> {
e.forEach(ee -> {
dWrapper.value += ee.getDistance();
});
});
int d = dWrapper.value;
... doing some other operation with d
}
public class IntWrapper {
public int value;
}
forEach
是错误的工具。
int d =
routeLists.stream() // Makes a Stream<List<Route>>
.flatMap(Collection::stream) // Makes a Stream<Route>
.mapToInt(Route::getDistance) // Makes an IntStream of distances
.sum();
或者只使用嵌套 for 循环:
int d = 0;
for (List<Route> rs : routeLists) {
for (Route r : rs) {
d += r.getDistance();
}
}
在流中使用的函数中不鼓励(甚至禁止?)有副作用。
更好的方法是
routeLists.stream()
.flatMapToInt(innerList -> innerList.stream()
.mapToInt(Route::getDistance))
.sum()
或
routeLists.stream()
.mapToInt(innerList -> innerList.stream()
.mapToInt(Route::getDistance).sum())
.sum()
第一个将为每个子列表创建一个距离流。所有这些流将变得扁平化并立即求和。
第二个将创建每个子列表的总和,然后再次将所有这些总和加在一起。
它们应该是等效的,但我不确定两者在性能方面是否更好(即,如果展平流比求和更昂贵)。
.
涵盖了展平列表然后获取和求和距离的第三种选择。
我想在 lambda 函数中使用局部变量,但出现错误: 请参阅代码中的 1. 和 2. 点。
class Foo {
int d = 0; // 1. It compiles, but ugly, 2. doesnt compile
public void findMax(List<List<Route>> routeLists) {
int d = 0; // 2.Error : Local variable dd defined in an enclosing scope must be final or effectively final
routeLists.forEach(e-> {
e.forEach(ee -> {
d+=ee.getDistance();
});
});
... doing some other operation with d
}
}
如何在不将它们设置为全局变量的情况下使用它们?
您不能将 int 用作变量,因为它必须是最终的才能在流中使用。
但是您可以创建一个 class 包装 int。
然后将持有这个class的变量声明为final。
正在更改内部 int 变量的内容。
public void findMax(List<List<Route>> routeLists) {
final IntWrapper dWrapper = new IntWrapper();
routeLists.forEach(e-> {
e.forEach(ee -> {
dWrapper.value += ee.getDistance();
});
});
int d = dWrapper.value;
... doing some other operation with d
}
public class IntWrapper {
public int value;
}
forEach
是错误的工具。
int d =
routeLists.stream() // Makes a Stream<List<Route>>
.flatMap(Collection::stream) // Makes a Stream<Route>
.mapToInt(Route::getDistance) // Makes an IntStream of distances
.sum();
或者只使用嵌套 for 循环:
int d = 0;
for (List<Route> rs : routeLists) {
for (Route r : rs) {
d += r.getDistance();
}
}
在流中使用的函数中不鼓励(甚至禁止?)有副作用。
更好的方法是
routeLists.stream()
.flatMapToInt(innerList -> innerList.stream()
.mapToInt(Route::getDistance))
.sum()
或
routeLists.stream()
.mapToInt(innerList -> innerList.stream()
.mapToInt(Route::getDistance).sum())
.sum()
第一个将为每个子列表创建一个距离流。所有这些流将变得扁平化并立即求和。
第二个将创建每个子列表的总和,然后再次将所有这些总和加在一起。
它们应该是等效的,但我不确定两者在性能方面是否更好(即,如果展平流比求和更昂贵)。