Java
java8
Stream
index
foreach

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 を使う等工夫してください。

以上