web-dev-qa-db-ja.com

インデックス付き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++;
});
116
Josh Stone

インデックス可能なコレクション(リストなど)を反復処理しているので、要素のインデックスを使用して反復処理を実行できると思います。

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

結果として得られるコードは、並列化が容易であることを除けば、古典的なi ++スタイルのforループを使用してリストを繰り返すのと似ています(もちろん、paramsへの同時読み取り専用アクセスが安全であると仮定します)。

133
srborlongan

現在のインデックスを保持している、1つの要素を持つ配列をキャプチャした場合は、paramsで動作します。

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

上記のコードでは、メソッドforEachが要素を遭遇順に反復することを前提としています。特に明記されていない限り、Iterableインタフェースはすべてのクラスに対してこの動作を指定します。どうやらそれは標準ライブラリからのIterableのすべての実装のために働きます、そして将来この振る舞いを変更することは下位互換性を壊すでしょう。

Collections/IterablesではなくStreamsを扱う場合は、forEachOrderedを使用する必要があります。forEachは同時に実行することができ、要素は異なる順序で出現することができます。次のコードは、シーケンシャルストリームとパラレルストリームの両方で機能します。

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

回避策はありますが、ストリームでそれを行うための、そして正直に言うためのクリーン/ショート/スイートな方法はありません。

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