我有一个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));
这只是使用从0
到recs.size() - 1
的数字流,并为每个数字调用recs.get
。