13

I want to know if the condition evaluation is executed in for and while loops in Java every time the loop cycle finishes.

Example:

int[] tenBig = new int[]{1,2,3,4,5,6,7,8,9,10};

for(int index = 0;index < tenBig.length;index++){
    System.out.println("Value at index: "+tenBig[index]);
}

Will the index < tenBig.length be execute every time the loop cycle finishes?

Assumption and experience tells me yes.

I know that in this example the tenBig.length is a constant, so there won't be a performance impact.

But lets assume that the condition operation takes long in a different case. I know the logical thing to do then is to assign the tenBig.length to a variable.

Still I want to be sure that its evaluated every time.

2
  • 1
    I know it is the case in c++. But is it for Java? Commented Oct 7, 2010 at 12:35
  • In your example, the middle part of the for will be evaluated 11 times. Once you fix the spelling of length so that it actually compiles, that is. Commented Oct 7, 2010 at 14:04

9 Answers 9

14

Yes, it will logically evaluate the whole of the middle operand on every iteration of the loop. In cases where the JIT knows better, of course, it can do clever things (even potentially removing the array bounds check within the loop, based on the loop conditions).

Note that for types that the JIT doesn't know about, it may not be able to optimize specifically like this - but may still inline things like fetching the size() of an ArrayList<T>.

Finally, I generally prefer the enhanced for loop for readability:

for (int value : tenBig) {
    ...
}

Of course, that's assuming you don't need the index for other reasons.

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

9 Comments

The enhanced for loop has a noteable improvement: the expression (tenBig in your case) is only evaluated once, according to the JLS.
The only thing I don't like about the "enhanced" loop is that it doesn't check for null values. In other words, if the tenBig object is null, a NullPointerException is thrown, which makes sense, but it would have been awesome if the object is checked for null beforehand.
@Koekiebox: What do you think it should do in that situation? Treat it as an empty collection? Personally I think an NPE is the right result here.
Yes, threat it as an empty collection. The reason being laziness.
@Jim: the terminating condition is just an arbitrary expression. I don't know why you would expect some of that condition to be executed every time, but some of it to only be executed once. (Would you expect a condition of totalDuration() > i to end up with radically different behavior, simply because it's the same condition written the other way round?)
|
6

Yes. Specifically, the condition part is executed before each loop body. So it's entirely possible that you never enter the body of the loop at all.

So taking your example:

for(int index = 0;index < tenBig.length;index++) {
    /* ...body... */
}

This is the logical (not literal) equivalent:

int index = 0;
while (index < tenBig.length) { // happens on each loop
    /* ...body... */

    index++;
}

2 Comments

The terminating condition is evaluated for each loop, but the right side of the condition is evaluated as well. What is the reasoning behind this? I was expecting that if we had for(int i = 0; i < totalDuration(); i++) then totalDuration() i.e. the code that controls the total number of loops would be called only once
@Jim - The whole thing (i < totalDuration()) is an expression, and nothing in the spec says that part of the expression will be remembered or reused. Remember that the expression can be anything (or nothing). But good news: If you want to call totalDuration() just once, in any of the languages I know that have for, you can do: for (int index = 0, max = totalDuration(); index < max; index++).
4

Yes, the expression must be evaluated for each iteration of the loop to determine whether to stay inside the loop or continue program execution.

Remember, you can do things like this:

for(int a = 0, z = 26; a < z; a++, z--){
    // Do some work
}

In that case, both sides of the expression will change and must be evaluated for each iteration.

And you're right, if you have calculations in the for loop condition that can be moved out to a separate variable, you should do that:

for(int i = 0; i < ((someCount / 2) * 21.6); i++){
}

Could easily be:

int maxVal = (someCount / 2) * 21.6;

for(int i=0; i < maxVal; i++){
{

Comments

2

Short Answer: the condition is evaluated every time so:

WRONG:

for (int i = 0; i < Math.random() * 50; i++) {
    System.out.println("" + i);
}

CORRECT:

double random = Math.random();
for (int i = 0; i < random * 50; i++) {
    System.out.println("" + i);
}

Comments

1

If the conditional expression is a loop invariant and you are running in JIT mode, loop optimizations such as Loop-invariant code motion can be done.

But when run in the interpreted mode, I guess there is not much optimization to do.

Comments

1

Here are several bytecode compiling examples from the JVM spec.

As far as I know, the condition will be evaluated every time.

Regards.

Comments

1

index < tenBig.length will be execute before every time the loop cycle starts.

    public static void main(String[] args) {
        int[] tenBig = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

        for (int index = 0; isEvaluated() && index < tenBig.length; index++) {
            System.out.println("Value at index: " + tenBig[index]);
        }
    }

    public static boolean isEvaluated() {
        System.out.println("evaluated");
        return true;
    }

It will print "evaluated" just before cycles starts. And one more time before loop finishes.

Comments

0

Do you ask wether the compiler caches the tenBig.length value since he knows it won't change during the loop? Or you ask wether the compiler automatically knows that the whole expression index < tenBig.length does not need to be evaluated for the next 9 times?

Comments

0

It's going to be executed everytime the loop is entered, including the last evaluation which will yield index < length = false . Aside from this, even though the length of tenBig is const, the loop will always access this property so it would be ideal to assign it to a variable (even though it's not a reasonable speed gain in your example).

Comments

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.