web-dev-qa-db-fra.com

Java 8 pourChaque avec index

Existe-t-il un moyen de construire une méthode forEach dans Java 8 qui effectue une itération avec un index? Idéalement, j'aimerais quelque chose comme ceci:

params.forEach((idx, e) -> query.bind(idx, e));

Le mieux que je puisse faire maintenant est:

int idx = 0;
params.forEach(e -> {
  query.bind(idx, e);
  idx++;
});
120
Josh Stone

Puisque vous parcourez une collection indexable (listes, etc.), je suppose que vous pouvez alors simplement itérer avec les index des éléments:

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

Le code résultant est similaire à l'itération d'une liste avec le style classique de boucle for i ++, sauf que la parallélisation est plus facile (en supposant, bien sûr, que l'accès simultané en lecture seule aux paramètres est sécurisé).

142
srborlongan

Cela fonctionne avec params si vous capturez un tableau avec un élément, qui contient l'index actuel.

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

Le code ci-dessus suppose que la méthode forEach itère à travers les éléments dans l'ordre de leur rencontre. L'interface Iterable spécifie ce comportement pour toutes les classes, sauf indication contraire. Apparemment, cela fonctionne pour toutes les implémentations de Iterable à partir de la bibliothèque standard, et modifier ce comportement à l'avenir romprait la compatibilité avec les versions antérieures.

Si vous travaillez avec Streams au lieu de Collections/Iterables, vous devez utiliser forEachOrdered, car forEach peut être exécuté simultanément et les éléments peuvent apparaître dans un ordre différent. Le code suivant fonctionne pour les flux séquentiels et parallèles:

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

Il existe des solutions de contournement, mais pas de méthode propre/courte/douce pour le faire avec des flux et pour être honnête, vous seriez probablement mieux avec:

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