Java 8 forEach с индексом
Есть ли способ построить метод forEach
в Java 8, который выполняет итерацию с индексом? В идеале мне бы хотелось что-то вроде этого:
params.forEach((idx, e) -> query.bind(idx, e));
Лучшее, что я мог сделать сейчас:
int idx = 0;
params.forEach(e -> {
query.bind(idx, e);
idx++;
});
Ответы
Ответ 1
Поскольку вы выполняете итерирование по индексируемой коллекции (списки и т.д.), я полагаю, что вы можете просто перебирать индексы элементов:
IntStream.range(0, params.size())
.forEach(idx ->
query.bind(
idx,
params.get(idx)
)
)
;
Полученный код похож на повторение списка с классическим циклом я ++ - style для цикла, за исключением упрощенной параллелизуемости (при условии, конечно, что одновременный доступ к параметрам доступен только для чтения).
Ответ 2
Он работает с параметрами, если вы захватили массив с одним элементом, который содержит текущий индекс.
int[] idx = { 0 };
params.forEach(e -> query.bind(idx[0]++, e));
В приведенном выше коде предполагается, что метод forEach выполняет итерацию через элементы в порядке выполнения. Интерфейс Iterable указывает это поведение для всех классов, если не указано иное. По-видимому, он работает для всех реализаций Iterable из стандартной библиотеки, и изменение этого поведения в будущем будет нарушать обратную совместимость.
Если вы работаете с Streams вместо Collections/Iterables, вы должны использовать forEachOder, потому что forEach может выполняться одновременно, и элементы могут выполняться в другом порядке. Следующий код работает как для последовательных, так и для параллельных потоков:
int[] idx = { 0 };
params.stream().forEachOrdered(e -> query.bind(idx[0]++, e));
Ответ 3
Есть обходные пути, но нет чистого/короткого/сладкого способа сделать это с потоками, и, честно говоря, вам, вероятно, будет лучше:
int idx = 0;
for (Param p : params) query.bind(idx++, p);