tags:

views:

224

answers:

8

Consider this code:

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);
      }


     }

}

It prints:

0 
0 
3 
0

What's this? For-each is supposed to run over all the elements in the array, why would it run arr[3]=0 but not arr[2]=0?

+2  A: 

because

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

doesnt set the array to 0s.

surely you meant to say

for(int i = 0; i < arr.length(); i++){
   arr[i] = 0;
}
mkoryak
huh? It is printing 0 0 3 0, instead of 1 2 3 4
omgzor
I'm not wondering on how to set an array to 0, I wanna know why for-each is zeroing some items and not others.
omgzor
Esko Luontola has done a good job of explaining why your code does what it's doing.
Otis
+2  A: 

You cannot use a foreach loop to set values in an array. The for each loop works a little differently than you expect.

(Explanation comming)

jjnguy
+1 ...beat me to it.
Justin Niessner
+26  A: 

If you look at what happens to arr in the first loop, it becomes obvious.

    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);
    }

This prints:

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

You are modifying the values in the array, using the values in the array as indexes. The "foreach" loop goes through the values of the array, not the indexes of the array. After removing the syntactic sugar, here is what your foreach loop actually is:

    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);
    }

To be able to index the array, you need to use the traditional for loop, like this:

    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);
    }
Esko Luontola
Yes it does, you're not seeing the underlying problem here (besides the fact that you are modifying your index values while you are using them).The index values *in* the array start with 1, but an array index is *zero-based*, meaning that the first value that get's modified is actually the *second* one in the array. So the second time through the loop your index is now zero (the first item in the array).
BCunningham
Because 2 disappears from the array before it gets a chance to modify that location.
jasonh
+8  A: 
int []arr = {1,2,3,4};
      for ( int i : arr )
      {
         arr[i] = 0;
       }

Watch arr in the debugger.

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)
Carl Manaster
+2  A: 

you have to be careful not to confuse index and value of an arrayelement

these are the values of the array before and after each iteration of the first loop, including the value of 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

Jens Schauder
+2  A: 

Don't confuse loop counters and array values... I think this happened here

raoulsson
+3  A: 

In Java, looping over an array using the

for (int i : arr)

syntax loops over the values in the array, not the indexes. This is different to the JavaScript loop

for (var i in arr)

that loops over indexes. Arrays are also indexed starting from 0 - the first item in the array is arr[0]. @Esko's answer shows what's actually happening.

Ben Lings
+1  A: 

Unroll the first loop:

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

So, arr[2] (the third element) is never set to zero; it retains its original value of 3.

erickson