如何在 java 中将普通 for 循环转换为并行流
How to convert normal for loop to parallel stream in java
我正在尝试将迭代 ArrayList 的正常 for 循环转换为并行循环。我遇到了 parallelStream.forEach() 和 parallelStream().collect(Collectors.toList()) 的概念。但不清楚如何转换。下面是普通 for 循环的示例代码:
public List<FinPlan> getFinPlanList() {
List<FinPlan> newList = new ArrayList<>();
// get list of string
List<String> finPlanIdsList = finPlanSearchRequest.getFinPlanIds();
// iterate list and add element to new list
for(String planId: finPlanIdsList) {
newList.add(retrieveFinPlan(planId));
}
return newList;
}
我尝试使用以下代码,但它给我的错误是“”newList should be final”。
finPlanIdsList.parallelStream().forEach( planId -> {
newList.add(retrieveFinPlan(planId));
});
所以,主要问题是如何将上面的正常循环转换为 parallelStream.forEach() 和 parallelStream().collect() ?
您当前版本中的编译错误是因为不允许 lambda 表达式使用局部变量,该局部变量在创建 lambda 时既不是 final
也不是有效的最终变量。
您可以尝试这样修复它:
final List<FinPlan> = new ArrayList<>();
...
finPlanIdsList.parallelStream().forEach( planId -> {
newList.add(retrieveFinPlan(planId));
});
...但这有一个更微妙的缺陷,即代码不是线程安全的。 newList
对象可能会从不同的线程更新...并且 ArrayList
不是线程安全的 class.
正确的解决方法是:
List<FinPlan> newList =
finPlanIdsList.parallelStream()
.map(planId -> retrieveFinPlan(planId))
.collect(Collectors.toList());
如果结果必须是 ArrayList
,您可以将 Collectors.toList()
表达式替换为 Collections.toCollection(ArrayList::new)
。
一般来说,流依赖副作用是个坏主意。在某些情况下,您会侥幸逃脱。在其他……没有。
您的方法定义似乎不正确,因为 getFinPlanList returns 是 FinPlan 而不是 List
此外,您不能在 lambda 表达式中使用不是最终有效的局部变量。因此它不会编译。
您可以尝试使用以下命令生成列表。请注意,应用并行流后,无法保证处理对象的顺序。
return finPlanIdsList.parallelStream().map(finPlanId->retrieveFinPlan(finPlanId)).collect(Collectors.toList());
我正在尝试将迭代 ArrayList 的正常 for 循环转换为并行循环。我遇到了 parallelStream.forEach() 和 parallelStream().collect(Collectors.toList()) 的概念。但不清楚如何转换。下面是普通 for 循环的示例代码:
public List<FinPlan> getFinPlanList() {
List<FinPlan> newList = new ArrayList<>();
// get list of string
List<String> finPlanIdsList = finPlanSearchRequest.getFinPlanIds();
// iterate list and add element to new list
for(String planId: finPlanIdsList) {
newList.add(retrieveFinPlan(planId));
}
return newList;
}
我尝试使用以下代码,但它给我的错误是“”newList should be final”。
finPlanIdsList.parallelStream().forEach( planId -> {
newList.add(retrieveFinPlan(planId));
});
所以,主要问题是如何将上面的正常循环转换为 parallelStream.forEach() 和 parallelStream().collect() ?
您当前版本中的编译错误是因为不允许 lambda 表达式使用局部变量,该局部变量在创建 lambda 时既不是 final
也不是有效的最终变量。
您可以尝试这样修复它:
final List<FinPlan> = new ArrayList<>();
...
finPlanIdsList.parallelStream().forEach( planId -> {
newList.add(retrieveFinPlan(planId));
});
...但这有一个更微妙的缺陷,即代码不是线程安全的。 newList
对象可能会从不同的线程更新...并且 ArrayList
不是线程安全的 class.
正确的解决方法是:
List<FinPlan> newList =
finPlanIdsList.parallelStream()
.map(planId -> retrieveFinPlan(planId))
.collect(Collectors.toList());
如果结果必须是 ArrayList
,您可以将 Collectors.toList()
表达式替换为 Collections.toCollection(ArrayList::new)
。
一般来说,流依赖副作用是个坏主意。在某些情况下,您会侥幸逃脱。在其他……没有。
您的方法定义似乎不正确,因为 getFinPlanList returns 是 FinPlan 而不是 List
此外,您不能在 lambda 表达式中使用不是最终有效的局部变量。因此它不会编译。 您可以尝试使用以下命令生成列表。请注意,应用并行流后,无法保证处理对象的顺序。
return finPlanIdsList.parallelStream().map(finPlanId->retrieveFinPlan(finPlanId)).collect(Collectors.toList());