2009-07-23 7 views
0

Considérez ce code:comportement sur Incohérence java de for-each

class Jm44 { 

public static void main(String args[]){ 

     int []arr = {1,2,3,4}; 
     for (int i : arr) 
     { 
     arr[i] = 0; 
     } 

     for (int i : arr) 
     { 
     System.out.println(i); 
     } 


    } 

} 

Il imprime:

0 
0 
3 
0 

Qu'est-ce? Pour-chacun est censé courir sur tous les éléments du tableau, pourquoi exécuterait-il arr[3]=0 mais pas arr[2]=0?

Répondre

26

Si vous regardez ce qui se passe à arr dans la première boucle, il devient évident.

int[] arr = {1, 2, 3, 4}; 
    for (int i : arr) { 
     System.out.println("i = " + i); 
     arr[i] = 0; 
     System.out.println("arr = " + Arrays.toString(arr)); 
    } 

    for (int i : arr) { 
     System.out.println(i); 
    } 

Cette impression:

 
i = 1 
arr = [1, 0, 3, 4] 
i = 0 
arr = [0, 0, 3, 4] 
i = 3 
arr = [0, 0, 3, 0] 
i = 0 
arr = [0, 0, 3, 0] 
0 
0 
3 
0 

Vous modifiez les valeurs dans le tableau, en utilisant les valeurs dans le tableau comme index. La boucle "foreach" passe par les valeurs du tableau, pas les index du tableau. Après avoir enlevé le sucre syntaxique, voici ce que votre boucle foreach est en fait:

int[] arr = {1, 2, 3, 4}; 
    for (int index = 0; index < arr.length; index++) { 
     int i = arr[index]; 
     arr[i] = 0; 
    } 

    for (int i : arr) { 
     System.out.println(i); 
    } 

Pour être en mesure d'indexer le tableau, vous devez utiliser la traditionnelle boucle, comme ceci:

int[] arr = {1, 2, 3, 4}; 
    for (int i = 0; i < arr.length; i++) { 
     arr[i] = 0; 
    } 

    for (int i : arr) { 
     System.out.println(i); 
    } 
+0

Oui c'est le cas, vous ne voyez pas le problème sous-jacent ici (outre le fait que vous modifiez vos valeurs d'index pendant que vous les utilisez). Les valeurs d'index * dans * le tableau commencent par 1, mais un index de tableau est * basé sur zéro *, signifiant que la première valeur qui est modifiée est en fait la * deuxième * dans le tableau. Donc, la deuxième fois dans la boucle, votre index est maintenant nul (le premier élément du tableau). – BCunningham

+0

Parce que 2 disparaît du tableau avant de pouvoir modifier cet emplacement. – jasonh

2

parce

for (int i : arr) 
     { 
     arr[i] = 0; 
     } 

ne marche pas mis le tableau à 0s.

sûrement vous voulu dire

for(int i = 0; i < arr.length(); i++){ 
    arr[i] = 0; 
} 
+0

hein? Il est l'impression 0 0 3 0, au lieu de 1 2 3 4 – andandandand

+0

Je ne me demande pas comment mettre un tableau à 0, je veux savoir pourquoi-chacun met à zéro certains éléments et pas d'autres. – andandandand

+0

Esko Luontola a fait un bon travail en expliquant pourquoi votre code fait ce qu'il fait. – Otis

2

Vous ne pouvez pas utiliser une boucle foreach pour définir les valeurs dans un tableau. Le pour chaque boucle fonctionne un peu différemment que prévu.

(Explication comming)

+0

+1 ... me battre pour ça. –

8
int []arr = {1,2,3,4}; 
     for (int i : arr) 
     { 
     arr[i] = 0; 
     } 

Observer arr dans le débogueur.

1,2,3,4 (initially) 
1,0,3,4 (after we change arr[arr[0]], or arr[1]) 
0,0,3,4 (after we change arr[arr[1]], or arr[0]) 
0,0,3,0 (after we change arr[arr[2]], or arr[3]) 
0,0,3,0 (after we change arr[arr[3]], or arr[0] (no change, actually) 
2

vous devez être prudent de ne pas confondre l'indice et la valeur d'un arrayelement

ce sont les valeurs du tableau avant et après chaque itération de la première boucle, y compris la valeur de i:

{1,2,3,4}

{1,0,3,4} i = 1

{0,0,3,4} i = 0

{0,0,3,0} i = 3

{0,0,3,0} i = 0

2

Ne confondez pas les compteurs de boucles et des valeurs de tableau ...Je pense que cela est arrivé ici

3

En Java, parcourir un tableau en utilisant les

for (int i : arr) 

boucles de syntaxe sur les valeurs dans le tableau, pas les index. Ceci est différent de la boucle JavaScript

for (var i in arr) 

qui passe en boucle sur les index. Les tableaux sont également indexés à partir de 0 - le premier élément du tableau est arr[0]. @ La réponse d'Esko montre ce qui se passe réellement.

1

Unroll la première boucle:

int[] arr = { 1, 2, 3, 4 }; 
int i; 
i = arr[0]; // i = 1 
arr[i] = 0; // arr[1] = 0 
i = arr[1]; // i = 0 
arr[i] = 0; // arr[0] = 0 
i = arr[2]; // i = 3 
arr[i] = 0; // arr[3] = 0 
i = arr[3]; // i = 0 
arr[i] = 0; // arr[0] = 0 

Ainsi, arr[2] (troisième élément) est jamais mis à zéro; il conserve sa valeur d'origine de 3.