Edited at

java8 の forEach を index つきで使いたい

More than 1 year has passed since last update.

java8 の forEach メソッドを使う際、インデックス(連番)がほしい場合があります。そのとき、カウンタ変数を使おうとするとラムダ内で更新できないので、配列を使うなどしないといけません。


こうしたいができない

int i = 1;

java.util.stream.Stream.of("a", "b", "c", "d").forEach(s -> {
System.out.println(i + ": " + s);
i++;
});


こうならできる

int i[] = { 1 };

java.util.stream.Stream.of("a", "b", "c", "d").forEach(s -> {
System.out.println(i[0] + ": " + s);
i[0]++;
});

どちらにしても見通しがよくないので、こんな感じにしたい。


こうしたい

java.util.stream.Stream.of("a", "b", "c", "d").forEach(withIndex((s, i) -> System.out.println(i + ": " + s)));


ということで、ユーティリティメソッドを作ってあげます。


クラス名、メソッド名は適当

import java.util.function.Consumer;

import java.util.function.ObjIntConsumer;

public class With {
public static <T> Consumer<T> B(int start, ObjIntConsumer<T> consumer) {
int counter[] = { start };
return obj -> consumer.accept(obj, counter[0]++);
}
}


初期値も設定できるようにしました。


できた

java.util.stream.Stream.of("a", "b", "c", "d").forEach(With.B(1, (s, i) -> System.out.println(i + ": " + s)));



実行結果

1: a

2: b
3: c
4: d

[注意] streamで並列実行する場合は forEachOrdered を使う等工夫してください。

以上