4

Which loop is faster, does it even make a difference?

final int cSize = getSize();
for(lineCount = 0; lineCount <= cSize; lineCount++) {
   // Do something!
}

or

for(lineCount = 0; linecount <= getSize(); lineCount++) {
   // Do something!
}

Where getSize() is a simple getter:

private int getSize() {
   return this.size;
}
octavio
  • 456
  • 4
  • 14
  • 1
    *Does it matter*? Have you found a case where one or other is a critical bottleneck in your program? If not, use the one which makes most sense, is easiest to read, maintain etc, and move on to worry about things that are more impactful. – Andy Turner Nov 21 '15 at 23:22
  • 2
    One reason to choose/not to choose one of the idioms is if another thread is modifying `this.size`, and you want/don't want the latest value of `this.size` in the thread doing the iteration. However, that is nothing to do with *performance*, but rather correctness. – Andy Turner Nov 21 '15 at 23:28
  • Using the final keyword is about consistency, but the question is about performance (if there is ?, not a satisfying answer written still), and it is a notable question. – Levent Divilioglu Nov 22 '15 at 01:02

2 Answers2

2

Assuming that this.size is not final, the two loops have different semantics:

  • The first loop will not react to changes in size done inside the loop; it will execute as many times as required by cSize variable.
  • The second loop will react to changes to size. If size increases or decreases, so would the number of loop iterations.

As far as the performance goes, Java's just-in-time compiler is smart enough to go straight for the this.size variable, effectively bypassing the getter. This produces performance that is very much identical.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
-3

Using this example for testing different for loops:

import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

public class ForLoopPerformanceTest {
private static List<Integer> list = new ArrayList<>();
private static long startTime;
private static long endTime;

static {
    for (int i = 0; i < 1_00_00_000; i++) {
        list.add(i);
    }
}

@SuppressWarnings("unused")
public static void main(String[] args) {
    // Type 1
    startTime = Calendar.getInstance().getTimeInMillis();
    for (Integer i : list) {
        //
    }
    endTime = Calendar.getInstance().getTimeInMillis();
    System.out.println("For each loop :: " + (endTime - startTime) + " ms");

    // Type 2
    startTime = Calendar.getInstance().getTimeInMillis();
    for (int j = 0; j < list.size(); j++) {
        //
    }
    endTime = Calendar.getInstance().getTimeInMillis();
    System.out.println("Using collection.size() :: " + (endTime - startTime) + " ms");

    // Type 3
    startTime = Calendar.getInstance().getTimeInMillis();
    int size = list.size();
    for (int j = 0; j < size; j++) {
        // System.out.println(j);
    }
    endTime = Calendar.getInstance().getTimeInMillis();
    System.out.println(
            "Using [int size = list.size(); int j = 0; j < size ; j++] :: " + (endTime - startTime) + " ms");

    // Type 4
    startTime = Calendar.getInstance().getTimeInMillis();
    for (int j = list.size(); j > size; j--) {
        // System.out.println(j);
    }
    endTime = Calendar.getInstance().getTimeInMillis();
    System.out.println("Using [int j = list.size(); j > size ; j--] :: " + (endTime - startTime) + " ms");
}
}

The Results

For each loop :: 108 ms

Using collection.size() :: 39 ms

Using [int size = list.size(); int j = 0; j < size ; j++] :: 4 ms

Using [int j = list.size(); j > size ; j--] :: 0 ms

GOXR3PLUS
  • 6,877
  • 9
  • 44
  • 93
  • You might want to read http://stackoverflow.com/questions/504103/how-do-i-write-a-correct-micro-benchmark-in-java – meriton Nov 22 '15 at 14:14