2

Are these statements completely the same in terms of memory occupation and efficiency in Java?

First:

Object[] array = new Object[100];
int i = 0;
for (; i < array.length; i++){
   Object o = array[i];
   //do something
}

Second:

Object[] array = new Object[100];
for (int i = 0; i < array.length; i++){
   Object o = array[i];
   //do something
}

Third:

Object[] array = new Object[100];
for (Object o : array){
   //do something
}

4 Answers 4

6

In terms of memory occupation and efficiency, yes. However, there are differences. In the first, i exists (has a scope) beyond the loop; while in the second it does not. In the third case, there is no (direct) way to access the index or to change the array contents at the position of the current object.

Sign up to request clarification or add additional context in comments.

4 Comments

Thank you very much. So in the second statement i'll have only one memory allocation for the iterator? Or different allocations for each iteration? And in the third... Java allocates an hidden iterator? And an hidden integer for the array lenght?
That's correct. If you are adventurous, you can use javap to look at the generated byte code for each kind of loop. They should be pretty close to identical.
Oh i didn't know about javap... Thank you again! :)
@Oneiros - I missed part of your earlier comment. The array length is evaluated anew each time through the loop. If you assign a different array to array, the loop test will respect the new length. There is a (very) tiny savings to be had by assigning the array length to a local variable and using that in the test (or else by iterating from array.length-1 down to 0). I seldom introduce an extra variable to store the array length just for that optimization.
1

The first one is not the common idiom; I wouldn't write it that way.

There's no memory or efficiency difference. The third is syntactic sugar that was added in a later JVM (I believe it was JDK 6).

Your code will be the memory and efficiency bottleneck, not your loop constructs.

1 Comment

The first idiom is very useful in cases where you want to break out of the loop under certain conditions and later need to know if there was a break and, if so, the index of the object that triggered it.
0

The third version was introduced with Java 5, is designed to simplify your work with generics. It is enhanced because you don't need to determine how many elements are in the array before looping. There is also no need to specify how to increment the current position, providing a cleaner implementation without having to create a counter variable or an Iterator.

1 Comment

I agree that the enhanced for-loop syntax is cleaner, provided you don't need the current index in the body of the loop. (For one thing, you don't need to worry about whether the body is mucking with the index variable.) In my opinion, though, it can more easily mask unintended autoboxing overhead (although not in this particular case).
0

No it's not exactly the same. And that's easily verifyable and imho not even that surprising.

Just decompile the following two functions:

public static void test1(Object[] arr) {
    for (int i = 0; i < arr.length; i++) {
        System.out.println(arr[i]);
    }
}

public void test2(Object[] arr) {
    for(Object o : arr) {
        System.out.println(o);
    }
}

and look at the output:

public static void test1(java.lang.Object[]);
  Code:
   0:   iconst_0
   1:   istore_1
   2:   iload_1
   3:   aload_0
   4:   arraylength
   5:   if_icmpge       23
   8:   getstatic       #4; //Field java/lang/System.out:Ljava/io/PrintStream;
   11:  aload_0
   12:  iload_1
   13:  aaload
   14:  invokevirtual   #5; //Method java/io/PrintStream.println:(Ljava/lang/Object;)V
   17:  iinc    1, 1
   20:  goto    2
   23:  return

public void test2(java.lang.Object[]);
  Code:
   0:   aload_1
   1:   astore_2
   2:   aload_2
   3:   arraylength
   4:   istore_3
   5:   iconst_0
   6:   istore  4
   8:   iload   4
   10:  iload_3
   11:  if_icmpge       34
   14:  aload_2
   15:  iload   4
   17:  aaload
   18:  astore  5
   20:  getstatic       #4; //Field java/lang/System.out:Ljava/io/PrintStream;
   23:  aload   5
   25:  invokevirtual   #5; //Method java/io/PrintStream.println:(Ljava/lang/Object;)V
   28:  iinc    4, 1
   31:  goto    8
   34:  return
}

I just included the println() so that we see something's done with the variable and to make sure javac doesn't optimize it away. Obviously in the bigger picture the difference won't matter and they're hardly measureable but still, not the same code ;)

Though I'm not sure what exactly's going on in the 2nd function, so if someone wants to take the time and dissect the code go on ;-)

1 Comment

Your first example doesn't exactly track OP's first example. You need to replace System.out.println(arr[i]); with Object o = arr[i]; System.out.println(o); to do a fair comparison. So only in test2 is each array element being stored in o (local variable #5). The second one is also doing a couple of things differently: it is caching the length of the array (in local variable #3) and it is copying arr to another local variable (#2). These differences are probably due to different bytecode templates being applied by the compiler.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.