J'ai une tradition pour la boucle ci-dessous et je me demande simplement quelle serait la boucle équivalente pour chaque boucle.

for (int i = 0; i < words.size(); i++)
{
    words.set(i, words.get(i).toUpperCase());
}

De plus, pour ceux qui se demandent, words est une arrayList de type String.

1
user7471732 26 janv. 2017 à 05:05

4 réponses

Meilleure réponse

For-each construct ne vous permet pas de définir un élément. Ceci parce que le sucre syntaxique qu'il fournit masque complètement le Iterator<E>.

for (String word : words)
 ...

Est équivalent à

for (Iterator<String> it = words.iterator(); it.hasNext(); /**/) {
  String word = it.next();
  ...
}

Cela pourrait fonctionner si les instances String étaient des objets mutables de sorte que vous puissiez modifier le contenu sans modifier la référence, mais ce n'est pas le cas. Pour pouvoir faire ce dont vous avez besoin avec un for-each, vous aurez besoin d'une classe wrapper, par exemple:

List<AtomicReference<String>> words = ...;
for (AtomicReference<String> word : words)
  word.set(word.get().toUpperCase());
3
Jack 26 janv. 2017 à 02:16

La boucle for avec index est bien, mais pour que vous le sachiez, vous pouvez également utiliser un ListIterator qui permet de remplacer l'élément actuel via set:

for (ListIterator<String> iterator = words.listIterator(); iterator.hasNext();) {
  String word = iterator.next();
  iterator.set(word.toUpperCase());
}

Ce qui n'est pas une boucle for améliorée, mais est très proche de ce qu'est réellement une boucle for améliorée avec des Iterable non-array.

3
weston 27 janv. 2017 à 16:23

Je suis surpris que personne n'ait indiqué la structure suivante, en utilisant une boucle for améliorée:

int i = 0;
for (String str : words) {
  words.set(i++, str.toUpperCase());
}

Maintenant, c'est assez grossier et inefficace à moins que words ne soit une instance de RandomAccess; Je préfère de loin utiliser l'approche ListIterator proposée par Weston.

Cela fonctionne pour ArrayList et LinkedList, etc. sans ConcurrentModificationException car cela n'est lancé qu'après modification structurelle de la liste:

Une modification structurelle est toute opération qui ajoute ou supprime un ou plusieurs éléments, ou redimensionne explicitement le tableau de support; la simple définition de la valeur d'un élément n'est pas une modification structurelle.

Notez qu'il n'y a pas d'approche sûre pour une implémentation générale List (y compris la boucle for de base dans la question d'origine): set est une opération facultative, et vous ne pouvez pas dire si elle est implémentée pour un List sans l'essayer.

1
Community 23 mai 2017 à 10:29

Peut-être seriez-vous intéressé par la façon java 8 de faire cela:

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

public class Class {
  public static void main(String... args) {
    List<String> words = new ArrayList<String>();
    words.add("hello");
    words = words.stream()
      .map(String::toUpperCase)
      .collect(Collectors.toList());
    System.out.println(words);
  }
}
1
Andreas 27 janv. 2017 à 15:50