web-dev-qa-db-fra.com

La boucle foreach de Java conserve-t-elle l'ordre?

La boucle foreach de Java commence-t-elle au premier objet et de manière linéaire va-t-elle jusqu'au bout? Par exemple

String[] names = new String[] {"Zoe", "Bob", "Charlie", "Alex"};
for(String name : names) {
  //do stuff...
}

La chaîne "Zoe" est-elle toujours traitée en premier, suivie de "Bob", etc.? Aucun tri ne se produit? Je l'ai testé moi-même et n'en ai trouvé aucune, mais j'ai besoin d'une garantie et je n'ai rien trouvé dans la documentation.

48
Celeritas

Oui. L'ordre n'est pas changé. Ceci s'applique à tous les types de collections du Java Collection Framework implémentant le interface itérateur utilisé par la boucle for. Si vous voulez trier votre tableau, vous pouvez utiliser Arrays.sort (noms)

41
Simulant

La boucle améliorée for est spécifiée dans JLS 14.14.2 , où son code équivalent est écrit.

Il peut être utilisé pour parcourir des tableaux et des instances de Iterable.

  • Pour un tableau, l'ordre des itérations sera toujours conservé et cohérent entre les exécutions. En effet, cela équivaut à une simple boucle for avec un index allant du début à la fin du tableau.

    La déclaration for améliorée est équivalente à une déclaration for de base de la forme:

    T[] #a = Expression;
    L1: L2: ... Lm:
    for (int #i = 0; #i < #a.length; #i++) {
        {VariableModifier} TargetType Identifier = #a[#i];
        Statement
    }
    

    #a Et #i Sont des identifiants générés automatiquement qui sont distincts de tout autre identifiant (généré automatiquement ou non) se trouvant dans la portée au moment où l'instruction for for améliorée se produit.

  • Pour un Iterable, il suivra l'ordre du Iterator correspondant (récupéré en appelant Iterable.iterator() ), qui peut être cohérent ou non entre pistes.

    La déclaration for améliorée est équivalente à une déclaration for de base de la forme:

    for (I #i = Expression.iterator(); #i.hasNext(); ) {
    {VariableModifier} TargetType Identifier =
        (TargetType) #i.next();
        Statement
    }
    

    #i Est un identifiant généré automatiquement, distinct de tout autre identifiant (généré automatiquement ou non) qui se trouve dans la portée (§6.3) au point où l'instruction à enrichir se produit.

    Vous devez vous référer à la Javadoc de chaque type pour voir si un ordre est cohérent ou non. Par exemple, il est explicitement spécifié que pour List, l'itérateur conserve l'ordre :

    Renvoie un itérateur sur les éléments de cette liste dans l'ordre approprié.

    While il est explicitement spécifié que pour Set, la commande n'est pas spécifiée (sauf si une garantie supplémentaire est fournie)) :

    Les éléments sont retournés sans ordre particulier (à moins que cet ensemble ne soit une instance d'une classe fournissant une garantie).

35
Tunaki