Java 8 forEach与索引

是否有一种方法可以在Java 8中构建一个forEach方法来迭代索引?理想情况下,我喜欢这样的东西:

params.forEach((idx, e) -> query.bind(idx, e));

我现在能做的就是

int idx = 0;
params.forEach(e -> {
query.bind(idx, e);
idx++;
});
328154 次浏览

有一些变通方法,但没有干净/简短/甜蜜的方式来处理流,老实说,你可能会更好:

int idx = 0;
for (Param p : params) query.bind(idx++, p);

或者更老的风格:

for (int idx = 0; idx < params.size(); idx++) query.bind(idx, params.get(idx));

如果你捕获一个包含当前索引的单元素数组,它就可以使用参数个数

int[] idx = { 0 };
params.forEach(e -> query.bind(idx[0]++, e));

上面的代码假设forEach方法按遇到顺序遍历元素。接口可迭代的为所有类指定此行为,除非另有文档。显然,它适用于标准库中的所有可迭代的实现,将来改变这种行为将破坏向后兼容性。

如果你使用的是而不是集合/iterable,你应该使用forEachOrdered,因为forEach可以并发执行,元素可以以不同的顺序出现。以下代码适用于顺序流和并行流:

int[] idx = { 0 };
params.stream().forEachOrdered(e -> query.bind(idx[0]++, e));

因为你是在一个可索引的集合(列表等)上迭代,我假设你可以只迭代元素的索引:

IntStream.range(0, params.size())
.forEach(idx ->
query.bind(
idx,
params.get(idx)
)
)
;

得到的代码类似于用经典i++风格的for循环迭代列表,只是可并行性更容易(当然,假设对params的并发只读访问是安全的)。