Skip to content
Java arrays 6 min read

Reverse an Array

Reversing an array is one of those classic tasks that looks simple on the surface but teaches you a lot about how arrays work in memory. Whether you need it for an interview, a sorting algorithm, or everyday data manipulation, Java gives you several ways to get it done.

The Two-Pointer Approach (Most Common)

The two-pointer technique is the go-to solution. You keep one index at the start and one at the end, swap the elements, then move both pointers inward until they meet in the middle. It reverses the array in-place — no extra array needed.

public class ReverseArray {
    public static void reverse(int[] arr) {
        int left = 0;
        int right = arr.length - 1;

        while (left < right) {
            // Swap arr[left] and arr[right]
            int temp = arr[left];
            arr[left] = arr[right];
            arr[right] = temp;

            left++;
            right--;
        }
    }

    public static void main(String[] args) {
        int[] numbers = {1, 2, 3, 4, 5};
        reverse(numbers);

        for (int n : numbers) {
            System.out.print(n + " ");
        }
    }
}

Output:

5 4 3 2 1

Note: This approach uses O(1) extra space (just one temp variable) and runs in O(n) time — optimal for arrays.

Why the Condition Is left < right

When the array has an odd number of elements, left and right will eventually point to the same middle element. Swapping it with itself is harmless, but stopping when left < right (rather than <=) skips that unnecessary step. For an even-length array, the pointers simply cross and the loop exits.

Using a Temporary Array (Extra Space)

If you prefer not to mutate the original array, you can copy elements into a new array in reverse order.

public class ReverseArrayCopy {
    public static int[] reverse(int[] arr) {
        int n = arr.length;
        int[] reversed = new int[n];

        for (int i = 0; i < n; i++) {
            reversed[i] = arr[n - 1 - i];
        }
        return reversed;
    }

    public static void main(String[] args) {
        int[] original = {10, 20, 30, 40, 50};
        int[] result = reverse(original);

        for (int n : result) {
            System.out.print(n + " ");
        }
    }
}

Output:

50 40 30 20 10

Tip: Use the extra-space approach when you need to preserve the original array for later use (e.g., comparison, logging, or undo functionality).

Using Collections.reverse() (for Object Arrays)

The Collections Utility Class provides a reverse() method, but it works only on List objects — not primitive arrays. You can wrap an array of objects in a List using Arrays.asList().

import java.util.Arrays;
import java.util.Collections;
import java.util.List;

public class ReverseWithCollections {
    public static void main(String[] args) {
        // Must be Integer[] (wrapper type), not int[]
        Integer[] numbers = {1, 2, 3, 4, 5};

        List<Integer> list = Arrays.asList(numbers);
        Collections.reverse(list);

        System.out.println(Arrays.toString(numbers));
    }
}

Output:

[5, 4, 3, 2, 1]

Warning: Arrays.asList() returns a fixed-size list backed by the original array. You cannot add or remove elements from it, but Collections.reverse() only does swaps, which is fine here. Also note this does not work with int[] — you must use Integer[].

Using the Stream API (Java 8+)

If you’re comfortable with the Stream API, you can reverse an array functionally. This is most natural for String[] or other object arrays.

import java.util.Arrays;
import java.util.stream.IntStream;

public class ReverseWithStream {
    public static void main(String[] args) {
        int[] arr = {1, 2, 3, 4, 5};

        int[] reversed = IntStream.rangeClosed(1, arr.length)
                .map(i -> arr[arr.length - i])
                .toArray();

        System.out.println(Arrays.toString(reversed));
    }
}

Output:

[5, 4, 3, 2, 1]

Tip: The stream approach is expressive and great for pipelines, but it allocates a new array. For performance-critical code, the two-pointer method wins.

Reversing a String Array

Reversing a String[] works exactly the same as reversing an int[] — just change the element type.

import java.util.Arrays;

public class ReverseStringArray {
    public static void main(String[] args) {
        String[] words = {"apple", "banana", "cherry", "date"};

        int left = 0, right = words.length - 1;
        while (left < right) {
            String temp = words[left];
            words[left] = words[right];
            words[right] = temp;
            left++;
            right--;
        }

        System.out.println(Arrays.toString(words));
    }
}

Output:

[date, cherry, banana, apple]

Reversing a 2D Array Row by Row

For multidimensional arrays, you can reverse each row independently.

import java.util.Arrays;

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

        for (int[] row : matrix) {
            int left = 0, right = row.length - 1;
            while (left < right) {
                int temp = row[left];
                row[left++] = row[right];
                row[right--] = temp;
            }
        }

        for (int[] row : matrix) {
            System.out.println(Arrays.toString(row));
        }
    }
}

Output:

[3, 2, 1]
[6, 5, 4]
[9, 8, 7]

Method Comparison

ApproachWorks onSpaceMutates originalReadability
Two-pointer (swap)any arrayO(1)YesHigh
Temporary arrayany arrayO(n)NoHigh
Collections.reverse()Object[] / ListO(1)YesHigh
Stream (IntStream)int[]O(n)NoMedium

For most situations, the two-pointer in-place swap is the best default — it’s simple, efficient, and universally applicable.

Under the Hood

When Java executes the two-pointer swap, there is no magic: the JVM simply performs three load/store operations on the array’s backing memory block. An int[] is stored as a contiguous block of 32-bit slots on the heap; swapping element i and element j directly reads and writes those memory addresses.

Because arrays in Java are objects on the heap and passed by reference, when you pass int[] arr to a method and modify it in place, the caller’s array is modified too — there’s no copy. See Call by Value for why Java is technically “call by value” even when it feels like “call by reference” for arrays.

The JIT compiler can further optimize the two-pointer loop by eliminating redundant bounds checks after it proves left and right stay within 0..length-1. This is called bounds-check elimination and is one reason tight array loops in Java are very fast in practice. Learn more in JIT Compilation & Bytecode.

Note: For very large arrays (millions of elements), cache efficiency matters. The two-pointer approach accesses memory from both ends converging inward — still cache-friendly because modern CPUs prefetch sequential memory in both directions.

Common Mistakes

  • Off-by-one errors — using left <= right instead of left < right works but causes a redundant no-op swap on the middle element of an odd-length array. Not a bug, just wasteful.
  • Using Collections.reverse() on int[] — this won’t compile. You must use Integer[] or convert to a List<Integer> first.
  • Forgetting that the original is mutated — in-place reversal permanently changes the array. If you need the original data, take a copy with Arrays.copyOf() before reversing.
import java.util.Arrays;

int[] original = {1, 2, 3, 4, 5};
int[] copy = Arrays.copyOf(original, original.length); // preserve original
// now reverse 'copy' safely

You can read more about the Arrays Utility Class for other handy helpers like Arrays.copyOf(), Arrays.sort(), and Arrays.fill().

Last updated June 13, 2026
Was this helpful?