我有一个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));
是否总体上有更好的方法?如果没有,有没有办法解决编译错误并仍然使用流? (而不是循环)
答案 0 :(得分:2)
这可以通过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
中修改状态,所以与其将index
设置在mapToObj
内,不如返回一个新对象。例如。像这样的东西:
.mapToObj(i -> {
Rec copy = new Rec(recs.get(i)); // copy constructor
copy.setRecordIndex(i);
return copy;
})
根据您使用的List
实现(使用 index-access 时,ArrayList
的效果要优于LinkedList
),也可以使用以下代码段。但是在生产代码中使用peek
有点争议。
IntStream.range(0, recs.size())
.peek(i -> recs.get(i).setRecordIndex(i))
.parallel()
.forEach(i -> foo(ProgressInfo, recs.get(i));
答案 1 :(得分:1)
您可以使用IntStream
:
IntStream.range(0, recs.size())
.forEach(i -> recs.get(i).setRecordIndex(i));
这只是使用从0
到recs.size() - 1
的数字流,并为每个数字调用recs.get
。