andandandand
andandandand

Reputation: 22270

Inconsistent behavior on java's for-each

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?

Upvotes: 0

Views: 685

Answers (8)

Ben Lings
Ben Lings

Reputation: 29423

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.

Upvotes: 3

Esko Luontola
Esko Luontola

Reputation: 73645

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

Upvotes: 26

erickson
erickson

Reputation: 269797

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.

Upvotes: 1

jjnguy
jjnguy

Reputation: 138902

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)

Upvotes: 2

raoulsson
raoulsson

Reputation: 16375

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

Upvotes: 2

Jens Schauder
Jens Schauder

Reputation: 81970

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

Upvotes: 2

Carl Manaster
Carl Manaster

Reputation: 40356

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) 

Upvotes: 8

mkoryak
mkoryak

Reputation: 57968

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

Upvotes: 2

Related Questions