Skip to main content
Java · lesson 7 of 66
Open the Java page →
Java beginner Lesson 7 of 66

Arrays in Java

Learn Java arrays — single and multi-dimensional arrays, array operations, sorting, searching, and the Arrays utility class.

By SkillByExample · Updated

An array is a fixed-size, ordered container of elements of one type. Arrays underpin collections, sorting algorithms and matrices, and they are zero-indexed: the first element is at index 0. Every example is a single file run with the JDK 21 source launcher (java File.java).

Creating arrays and default values

Create an array either with a size (Java fills it with defaults) or with the values inline.

import java.util.Arrays;

public class Create {
    public static void main(String[] args) {
        int[] scores = new int[3];
        double[] temps = new double[2];
        boolean[] flags = new boolean[2];
        char[] letters = new char[2];
        String[] names = new String[2];
        int[] primes = {2, 3, 5, 7, 11};

        System.out.println(Arrays.toString(scores));
        System.out.println(Arrays.toString(temps));
        System.out.println(Arrays.toString(flags));
        System.out.println((int) letters[0]);
        System.out.println(Arrays.toString(names));
        System.out.println(Arrays.toString(primes) + " length=" + primes.length);
        System.out.println(primes);
    }
}
$ java Create.java
[0, 0, 0]
[0.0, 0.0]
[false, false]
0
[null, null]
[2, 3, 5, 7, 11] length=5
[I@20d3d15a

Numbers default to zero, boolean to false, references to null, and char to the character with code 0 ('\u0000'), which is why it is printed as an int. The last line is what happens without Arrays.toString: [I means “array of int”, and the hex part is an identity hash that changes between runs.

Accessing elements and going out of bounds

Valid indices run from 0 to length - 1. One past the end compiles fine and fails at runtime.

public class Access {
    public static void main(String[] args) {
        int[] nums = {10, 20, 30, 40, 50};
        System.out.println(nums[0]);
        System.out.println(nums[nums.length - 1]);
        nums[2] = 99;
        System.out.println(nums[2]);
        System.out.println(nums[5]);
    }
}
$ java Access.java
10
50
99
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 5 out of bounds for length 5
	at Access.main(Access.java:8)

The first three lines printed before the crash. nums[nums.length - 1] is the safe way to reach the last element without hard-coding the size.

Iterating

Use an index-based for when you need the position and the enhanced for when you only need the values.

public class Iterate {
    public static void main(String[] args) {
        int[] scores = {85, 92, 78, 95, 88};
        for (int i = 0; i < scores.length; i++) {
            System.out.println("Score " + i + ": " + scores[i]);
        }
        int total = 0;
        for (int s : scores) total += s;
        System.out.println("Integer average: " + total / scores.length);
        System.out.printf("Real average: %.1f%n", (double) total / scores.length);
    }
}
$ java Iterate.java
Score 0: 85
Score 1: 92
Score 2: 78
Score 3: 95
Score 4: 88
Integer average: 87
Real average: 87.6

total / scores.length is int / int, so the .6 is thrown away. Casting one side to double first keeps it.

The Arrays utility class

java.util.Arrays sorts, searches, fills, copies and compares, so you rarely write these loops by hand.

import java.util.Arrays;

public class Utils {
    public static void main(String[] args) {
        int[] arr = {64, 25, 12, 22, 11};
        Arrays.sort(arr);
        System.out.println(Arrays.toString(arr));
        System.out.println("22 at " + Arrays.binarySearch(arr, 22));
        System.out.println("23 at " + Arrays.binarySearch(arr, 23));

        int[] copy = Arrays.copyOf(arr, arr.length);
        int[] slice = Arrays.copyOfRange(arr, 1, 4);
        System.out.println(Arrays.toString(slice));
        System.out.println("equals: " + Arrays.equals(arr, copy) + ", same object: " + (arr == copy));

        int[] sevens = new int[4];
        Arrays.fill(sevens, 7);
        System.out.println(Arrays.toString(sevens));
    }
}
$ java Utils.java
[11, 12, 22, 25, 64]
22 at 2
23 at -4
[12, 22, 25]
equals: true, same object: false
[7, 7, 7, 7]

binarySearch returns -(insertion point) - 1 for a missing value: 23 would go at index 3, so the result is -4. A copy has equal contents but is a different object, which is why equals and == disagree. binarySearch only works on a sorted array; on an unsorted one its result is undefined.

Arrays are references

Assigning an array to another variable copies the reference, not the elements.

import java.util.Arrays;

public class Alias {
    public static void main(String[] args) {
        int[] a = {1, 2, 3};
        int[] b = a;
        int[] c = a.clone();
        b[0] = 100;
        System.out.println("a = " + Arrays.toString(a));
        System.out.println("c = " + Arrays.toString(c));
        doubleAll(a);
        System.out.println("a = " + Arrays.toString(a));
    }

    static void doubleAll(int[] arr) {
        for (int i = 0; i < arr.length; i++) arr[i] *= 2;
    }
}
$ java Alias.java
a = [100, 2, 3]
c = [1, 2, 3]
a = [200, 4, 6]

Writing through b changed a because both names point at one array; clone() made c an independent copy. Passing an array to a method passes the same reference, so doubleAll changes the caller’s array.

Two-pointer reverse

Swap from both ends toward the middle to reverse in place with no extra array.

import java.util.Arrays;

public class Reverse {
    public static void main(String[] args) {
        int[] arr = {1, 2, 3, 4, 5};
        int left = 0, right = arr.length - 1;
        while (left < right) {
            int temp = arr[left];
            arr[left++] = arr[right];
            arr[right--] = temp;
        }
        System.out.println(Arrays.toString(arr));
    }
}
$ java Reverse.java
[5, 4, 3, 2, 1]

With five elements the pointers meet at index 2 and the loop stops; the middle element never moves.

2D arrays

A 2D array is an array of arrays: matrix[row][col]. matrix.length is the number of rows, matrix[r].length the length of row r.

import java.util.Arrays;

public class Grid {
    public static void main(String[] args) {
        int[][] matrix = {
            {1, 2, 3},
            {4, 5, 6}
        };
        System.out.println(matrix[1][2] + " rows=" + matrix.length + " cols=" + matrix[0].length);
        for (int[] row : matrix) {
            for (int v : row) System.out.printf("%3d", v);
            System.out.println();
        }
        System.out.println(Arrays.toString(matrix));
        System.out.println(Arrays.deepToString(matrix));
    }
}
$ java Grid.java
6 rows=2 cols=3
  1  2  3
  4  5  6
[[I@212bf671, [I@14a2f921]
[[1, 2, 3], [4, 5, 6]]

Arrays.toString on a 2D array prints the inner array references; deepToString recurses into them.

Jagged arrays

Rows do not have to be the same length. Create the outer array with only the row count and assign each row separately.

import java.util.Arrays;

public class Jagged {
    public static void main(String[] args) {
        int[][] triangle = new int[4][];
        for (int r = 0; r < triangle.length; r++) {
            triangle[r] = new int[r + 1];
            triangle[r][0] = triangle[r][r] = 1;
            for (int c = 1; c < r; c++) {
                triangle[r][c] = triangle[r - 1][c - 1] + triangle[r - 1][c];
            }
        }
        for (int[] row : triangle) System.out.println(Arrays.toString(row));
    }
}
$ java Jagged.java
[1]
[1, 1]
[1, 2, 1]
[1, 3, 3, 1]

Each row of Pascal’s triangle is one longer than the last, so a rectangular int[4][4] would waste space; new int[4][] leaves every row null until it is assigned.

Project: student marks

Parallel arrays hold the names and marks; the input comes from command-line arguments.

public class StudentMarks {
    public static void main(String[] args) {
        int n = args.length / 2;
        String[] names = new String[n];
        int[] marks = new int[n];
        for (int i = 0; i < n; i++) {
            names[i] = args[2 * i];
            marks[i] = Integer.parseInt(args[2 * i + 1]);
        }
        int top = 0, total = 0;
        for (int i = 0; i < n; i++) {
            total += marks[i];
            if (marks[i] > marks[top]) top = i;
        }
        System.out.printf("Class average: %.1f%n", (double) total / n);
        System.out.printf("Top scorer: %s (%d)%n", names[top], marks[top]);
    }
}
$ java StudentMarks.java Alice 78 Bob 92 Charlie 85
Class average: 85.0
Top scorer: Bob (92)

args is itself a String[]. Index 2 * i holds a name and 2 * i + 1 its mark, so the two arrays stay aligned by position — the weakness of parallel arrays is that a sort must move both in lockstep (Practice task 4).

Practice

  1. Rotate an array left by one position in place, so {1, 2, 3, 4, 5} becomes {2, 3, 4, 5, 1}.
Solution
import java.util.Arrays;

public class RotateLeft {
    public static void main(String[] args) {
        int[] arr = {1, 2, 3, 4, 5};
        int first = arr[0];
        for (int i = 0; i < arr.length - 1; i++) arr[i] = arr[i + 1];
        arr[arr.length - 1] = first;
        System.out.println(Arrays.toString(arr));
    }
}
$ java RotateLeft.java
[2, 3, 4, 5, 1]

Saving arr[0] before the shift overwrites it is what makes the in-place rotation work.

  1. Find the second-largest distinct value in {4, 2, 9, 7, 9, 1} in one pass, without sorting.
Solution
public class SecondLargest {
    public static void main(String[] args) {
        int[] nums = {4, 2, 9, 7, 9, 1};
        int max = Integer.MIN_VALUE, second = Integer.MIN_VALUE;
        for (int n : nums) {
            if (n > max) { second = max; max = n; }
            else if (n > second && n != max) second = n;
        }
        System.out.println("max=" + max + " second=" + second);
    }
}
$ java SecondLargest.java
max=9 second=7

When a new max arrives, the old max becomes the second; n != max stops the duplicate 9 from also becoming the second-largest.

  1. Sum every element of the jagged array {{1}, {2, 3}, {4, 5, 6}} and print each row’s sum too.
Solution
public class SumJagged {
    public static void main(String[] args) {
        int[][] jagged = {{1}, {2, 3}, {4, 5, 6}};
        int total = 0;
        for (int[] row : jagged) {
            int rowSum = 0;
            for (int v : row) rowSum += v;
            System.out.println("row sum " + rowSum);
            total += rowSum;
        }
        System.out.println("total " + total);
    }
}
$ java SumJagged.java
row sum 1
row sum 5
row sum 15
total 21

The enhanced for never reads a row’s length explicitly, so different row lengths need no special case.

  1. Extend StudentMarks to print a ranking from highest to lowest mark, keeping each name with its mark.
Solution
public class Ranking {
    public static void main(String[] args) {
        String[] names = {"Alice", "Bob", "Charlie"};
        int[] marks = {78, 92, 85};
        for (int i = 0; i < marks.length - 1; i++) {        // selection sort, descending
            int best = i;
            for (int j = i + 1; j < marks.length; j++) if (marks[j] > marks[best]) best = j;
            int m = marks[i]; marks[i] = marks[best]; marks[best] = m;
            String s = names[i]; names[i] = names[best]; names[best] = s;
        }
        for (int i = 0; i < marks.length; i++) {
            System.out.printf("%d. %s (%d)%n", i + 1, names[i], marks[i]);
        }
    }
}
$ java Ranking.java
1. Bob (92)
2. Charlie (85)
3. Alice (78)

Every swap in marks is mirrored in names; forget one and the names drift away from their marks. That fragility is why real code puts both in one object (a record Student(String name, int mark)) and sorts an array of those.

  1. Add two 2×3 matrices element by element and print the result with Arrays.deepToString.
Solution
import java.util.Arrays;

public class MatrixAdd {
    public static void main(String[] args) {
        int[][] a = {{1, 2, 3}, {4, 5, 6}};
        int[][] b = {{7, 8, 9}, {1, 2, 3}};
        int[][] sum = new int[a.length][a[0].length];
        for (int i = 0; i < a.length; i++)
            for (int j = 0; j < a[i].length; j++)
                sum[i][j] = a[i][j] + b[i][j];
        System.out.println(Arrays.deepToString(sum));
    }
}
$ java MatrixAdd.java
[[8, 10, 12], [5, 7, 9]]

The result array is created with the same shape as the inputs; new int[rows][cols] starts it at all zeros.

Frequently Asked Questions

What is the difference between an array and an ArrayList?
An array has a fixed size set at creation — you cannot add or remove elements. An ArrayList is a resizable list backed by an array that grows automatically. Use arrays when size is known and fixed; use ArrayList when you need dynamic sizing.
Why does Java throw ArrayIndexOutOfBoundsException?
You're accessing an index that doesn't exist. Array indices run from 0 to length-1. Accessing index 5 on a 5-element array (valid indices: 0-4) throws this exception.
How do I copy an array in Java?
Use Arrays.copyOf(original, length) for a new array of a given length, Arrays.copyOfRange(original, from, to) for a slice, or System.arraycopy for copying into an existing destination array.
Why does printing a Java array show something like [I@1b6d3586?
Arrays do not override toString, so println prints the type code ([I means int array) and an identity hash. Use Arrays.toString(array) for a one-dimensional array and Arrays.deepToString(array) for nested arrays to see the elements.