If performance is what you want, I would bet my money on this:
for(int i = 0; i < arr.length; i+=2) {
// do even stuff
}
for(int i = 1; i < arr.length; i+=2) {
// do odd stuff
}
That way you can just skip the whole if-else
part. And it is way more as fast as the "and" version. Let me show you; here we've got 4 different implementations of the same method:
private static long withModulus(int[] arr) {
long elapsedTime = System.nanoTime();
for(int i = 0; i < arr.length; i++) {
List list;
if ((i % 2) == 0) {
list = new ArrayList<>();
list.add(new Object());
} else {
list = new LinkedList<>();
list.add(new Object());
}
}
return (System.nanoTime() - elapsedTime);
}
private static long withFlag(int[] arr) {
long elapsedTime = System.nanoTime();
for(int i = 0; i < arr.length; i++) {
List list;
boolean flag = true;
if (flag) {
list = new ArrayList<>();
list.add(new Object());
flag = false;
} else {
list = new LinkedList<>();
list.add(new Object());
flag = true;
}
}
return (System.nanoTime() - elapsedTime);
}
private static long withAnd(int[] arr) {
long elapsedTime = System.nanoTime();
for(int i = 0; i < arr.length; i++) {
List list;
if ((i & 1) == 1) {
list = new ArrayList<>();
list.add(new Object());
} else {
list = new LinkedList<>();
list.add(new Object());
}
}
return (System.nanoTime() - elapsedTime);
}
private static long withTwoLoops(int[] arr) {
long elapsedTime = System.nanoTime();
for(int i = 0; i < arr.length; i+=2) {
List list;
list = new ArrayList<>();
list.add(new Object());
}
for(int i = 1; i < arr.length; i+=2) {
List list;
list = new LinkedList<>();
list.add(new Object());
}
return (System.nanoTime() - elapsedTime);
}
And now for the timing part:
public static void main(String[] args) {
int[] arr = new int[10000000];
// Warm up
withModulus(arr);
withFlag(arr);
withAnd(arr);
withTwoLoops(arr);
// Timing
int iterations = 100;
long meanModulus = 0, meanFlag = 0, meanAnd = 0, meanTwoLoops = 0;
for (int i = 0; i < iterations; i++) {
meanModulus += withModulus(arr);
}
for (int i = 0; i < iterations; i++) {
meanFlag += withFlag(arr);
}
for (int i = 0; i < iterations; i++) {
meanAnd += withAnd(arr);
}
for (int i = 0; i < iterations; i++) {
meanTwoLoops += withTwoLoops(arr);
}
System.out.println("Modulus: "+(meanModulus/iterations)+" ms");
System.out.println("Flag: "+(meanFlag/iterations)+" ms");
System.out.println("And: "+(meanAnd/iterations)+" ms");
System.out.println("Two loops: "+(meanTwoLoops/iterations)+" ms");
}
Results:
Modulus: 82331604 ms
Flag: 96305740 ms
And: 80845864 ms
Two loops: 79633999 ms
You can try with different array sizes, but for anything bigger than 10000 the two-loops option is the fastest.
After many different runs and tests, some times the "and" version is fastest, some times the "two loops" is. Even the "modulus" version came up as fastest in one of the tests. In production, it will mostly depend on what you do inside the loop, not on the condition itself.