我如何为要并行处理的java列表中的每个项添加索引



我有一个Rec的列表,我想通过调用一些方法foo()来并行处理它们。

foo()可以将一些Rec标记为错误的,并且在结束时,所有错误记录都由它们的索引位置报告(例如,"记录12无效"(
所以我想将每个Rec的索引位置传递给foo((,或者在调用foo之前将索引设置到每个Rec中
我尝试做的(如下所示(是首先按顺序将索引设置为每个Rec,然后在每个上并行调用foo。有更好的方法吗?

List<Rec> recs;
class Rec {
private int recordIndex;
public void setRecordIndex( int index) { recordIndex = index; }
//more memebers and getter to the above...
}
//somewhere in the code
int index = 0;
recs.stream().forEach(rec -> rec.setRecordIndex(index++));
//the compiler complains about the index++ above, says it should be final
rec.parallelStream().forEach(rec -> foo(ProgressInfo, rec));

总的来说,有更好的方法吗?如果没有,有没有办法修复编译错误并仍然使用流?(而不是循环(

这可以用IntStream完成,我也建议只使用一个Stream:

IntStream.range(0, recs.size())
.mapToObj(i -> {
Rec rec = recs.get(i);
rec.setRecordIndex(i);
return rec;
})
.parallel()
.forEach(rec -> foo(ProgressInfo, rec));

尽管不鼓励修改streams中的状态,因此与其在mapToObj中设置index,不如返回一个新对象。例如:

.mapToObj(i -> {
Rec copy = new Rec(recs.get(i)); // copy constructor
copy.setRecordIndex(i);
return copy;
})

根据您正在使用的List实现(当使用索引访问时,ArrayList的性能优于LinkedList(,您也可以使用以下代码段。但是peek在生产代码中的使用有点争议。

IntStream.range(0, recs.size())
.peek(i -> recs.get(i).setRecordIndex(i))
.parallel()
.forEach(i -> foo(ProgressInfo, recs.get(i));

您可以使用IntStream:

IntStream.range(0, recs.size())
.forEach(i -> recs.get(i).setRecordIndex(i));

这只是使用从0recs.size() - 1的数字流,并为每个数字调用recs.get

最新更新