我正试图将正常的for循环迭代数组列表转换为并行列表。我遇到了parallelStream. foreach()和parallelStream().collect(collections . 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应该是final"
finPlanIdsList.parallelStream().forEach( planId -> {
newList.add(retrieveFinPlan(planId));
});
所以,主要的问题是如何将上面的普通循环转换为parallelStream. foreach()和parallelStream().collect() ?
当前版本的编译错误正在发生,因为lambda表达式在创建lambda时不允许使用既不是final
也不是有效final的局部变量。
你可以试着这样修改:
final List<FinPlan> = new ArrayList<>();
...
finPlanIdsList.parallelStream().forEach( planId -> {
newList.add(retrieveFinPlan(planId));
});
…但这有一个更微妙的缺陷,即代码不是线程安全的。newList
对象可能会从不同的线程更新…ArrayList
不是一个线程安全的类。
正确的解决方法是:
List<FinPlan> newList =
finPlanIdsList.parallelStream()
.map(planId -> retrieveFinPlan(planId))
.collect(Collectors.toList());
如果结果必须是ArrayList
,则可以将Collectors.toList()
表达式替换为Collections.toCollection(ArrayList::new)
。
你的方法定义似乎是不正确的,因为getFinPlanList返回一个FinPlan而不是List
此外,您不能在lambda表达式中使用非有效final的局部变量。因此它不会编译。您可以尝试使用以下命令来生成列表。注意,一旦应用parallelstream,对象的处理顺序就不能保证了。
return finPlanIdsList.parallelStream().map(finPlanId->retrieveFinPlan(finPlanId)).collect(Collectors.toList());