前置き
i02302さんのJava8以降のStream.mapでindexをつけるでStreamの各要素にindexを付加する方法が書かれていました。
最初に見たときはindexのカウンターに配列を使っていて、並列Streamも考慮してAtomicIntegerにした方がいいんじゃないかな…と思っていましたが、さっき見たらそう変わっていました(笑)
あとは、intのindex部分がBiFuntionを使うとIntegerになってしまうので、関数型インターフェースも独自に用意した方がよいのではないかと思います。
public interface BiIntFunction<T, R> {
public R apply(T t, int n);
}
public class WithIndex {
public static <T, R> Function<T, R> apply(int start, BiIntFunction<T, R> function) {
AtomicInteger counter = new AtomicInteger(start);
return object -> function.apply(object, counter.getAndAdd(1));
}
}
stream.map(WithIndex.apply(1, (obj, i) -> obj + i))
タプルを用意する方法
ScalaのzipWithIndexだと要素とインデックスのペア(タプル)を返すので、それと同様にする方法もあると思います。
public class ObjectIndexPair<T> {
private final T object;
private final int index;
private ObjectIndexPair(T object, int index) {
this.object = object;
this.index = index;
}
public T getObject() {
return object;
}
public int getIndex() {
return index;
}
public static <T> Function<T, ObjectIndexPair<T>> start(int start) {
AtomicInteger counter = new AtomicInteger(start);
return object -> new ObjectIndexPair<>(object, counter.getAndAdd(1));
}
}
stream.map(ObjectIndexPair.start(1)).map(pair -> pair.getObject() + pair.getIndex())