Reversing an array
Two indices walking toward each other. The whole exercise is where they stop.
public static void reverse(int[] a) {
for (int i = 0, j = a.length - 1; i < j; i++, j--) {
int tmp = a[i];
a[i] = a[j];
a[j] = tmp;
}
}
One index starts at the front, one at the back, and they swap and step inward.
The condition
i < j, not i <= j and not i < a.length.
With i <= j and an odd length the middle element is swapped with itself — harmless but pointless. With i < a.length every element is swapped twice and the array comes back unchanged, which is the classic wrong answer to this exercise and looks correct until you test it.
Stopping at i < j also means no special case for odd lengths: the middle element is already where it belongs.
In place, or a copy
The version above modifies the caller’s array — there is nothing to return. If the original must survive:
public static int[] reversed(int[] a) {
int[] out = new int[a.length];
for (int i = 0; i < a.length; i++) {
out[i] = a[a.length - 1 - i];
}
return out;
}
a.length - 1 - i is the mirror index. Off by one here is the other standard mistake — a.length - i overruns on the first iteration.
For objects
The same code works with an object array; only the type of tmp changes. A generic version:
public static <T> void reverse(T[] a) { ... }
Why not Collections.reverse
Collections.reverse takes a List, and an array is not one. This nearly works:
Collections.reverse(Arrays.asList(strings)); // works for object arrays
Arrays.asList wraps the array, and writes through to it, so the array really is reversed.
It does not work for primitives. Arrays.asList(intArray) produces a List<int[]> with a single element — the array itself — rather than a list of integers. It compiles and does nothing, which is worse than failing.
For a primitive array, write the loop or use a stream:
int[] out = IntStream.range(0, a.length)
.map(i -> a[a.length - 1 - i])
.toArray();
The loop is clearer and faster. This is one of the places where the stream version is not an improvement.