Java Arrays

BEGINNER ~8 min read Tutorial

An array is a fixed-length, indexed sequence of values of the same type. It is the most fundamental data structure in Java — even an ArrayList uses an array internally. Arrays are fast (O(1) random access), memory-efficient, and have direct language syntax for creation and access.

This tutorial covers declaration, creation, iteration, the enhanced for-each loop, multi-dimensional arrays, the Arrays utility class, and the modern alternatives (List.of, Stream) that you should often prefer.

1. Declaring and Creating

Array types are written with [] after the element type. You can declare, create, and initialise in several ways:

java
class=class="tok-str">"tok-cmt">// declare, size known, default-initialised to class="tok-num">0 / null / false
int[] nums = new int[class="tok-num">5];                  class=class="tok-str">"tok-cmt">// [class="tok-num">0, class="tok-num">0, class="tok-num">0, class="tok-num">0, class="tok-num">0]
String[] names = new String[class="tok-num">3];           class=class="tok-str">"tok-cmt">// [null, null, null]

class=class="tok-str">"tok-cmt">// declare with initial values
int[] primes = {class="tok-num">2, class="tok-num">3, class="tok-num">5, class="tok-num">7, class="tok-num">11};          class=class="tok-str">"tok-cmt">// length class="tok-num">5
String[] days = {"Mon", "Tue", "Wed"};

class=class="tok-str">"tok-cmt">// declare then assign later
double[] temps;
temps = new double[]{class="tok-num">98.6, class="tok-num">100.4, class="tok-num">99.1};

class=class="tok-str">"tok-cmt">// array of zero elements - legal but rarely useful
int[] empty = new int[class="tok-num">0];

The length of an array is fixed at creation time. You cannot grow an array; you must create a new one (or use an ArrayList).

2. Accessing and Modifying Elements

Elements are accessed by index, starting at 0:

java
int[] nums = {class="tok-num">10, class="tok-num">20, class="tok-num">30, class="tok-num">40, class="tok-num">50};

int first  = nums[class="tok-num">0];   class=class="tok-str">"tok-cmt">// class="tok-num">10
int third  = nums[class="tok-num">2];   class=class="tok-str">"tok-cmt">// class="tok-num">30
int length = nums.length;   class=class="tok-str">"tok-cmt">// class="tok-num">5  (length is a field, not a method)

nums[class="tok-num">1] = class="tok-num">99;           class=class="tok-str">"tok-cmt">// array is now [class="tok-num">10, class="tok-num">99, class="tok-num">30, class="tok-num">40, class="tok-num">50]

class=class="tok-str">"tok-cmt">// out-of-bounds throws ArrayIndexOutOfBoundsException
int bad = nums[class="tok-num">10];    class=class="tok-str">"tok-cmt">// runtime error

Out-of-bounds access throws ArrayIndexOutOfBoundsException at runtime — the JVM checks every access. There is no “undefined” in Java arrays.

3. Iterating

Three common iteration patterns:

java
int[] nums = {class="tok-num">10, class="tok-num">20, class="tok-num">30, class="tok-num">40, class="tok-num">50};

class=class="tok-str">"tok-cmt">// class="tok-num">1. classic indexed for
for (int i = class="tok-num">0; i < nums.length; i++) {
    System.out.println(nums[i]);
}

class=class="tok-str">"tok-cmt">// class="tok-num">2. enhanced for-each (no index available)
for (int n : nums) {
    System.out.println(n);
}

class=class="tok-str">"tok-cmt">// class="tok-num">3. with index using a stream (IntStream)
IntStream.range(class="tok-num">0, nums.length)
    .forEach(i -> System.out.println(i + ": " + nums[i]));

Use for-each when you do not need the index. Use the classic for when you do.

4. Multi-Dimensional Arrays

Java has no true multi-dimensional arrays. Instead, an array of arrays is used, and each row can have a different length (a ragged array):

java
class=class="tok-str">"tok-cmt">// rectangular 3x3
int[][] grid = {
    {class="tok-num">1, class="tok-num">2, class="tok-num">3},
    {class="tok-num">4, class="tok-num">5, class="tok-num">6},
    {class="tok-num">7, class="tok-num">8, class="tok-num">9}
};

System.out.println(grid[class="tok-num">1][class="tok-num">2]);   class=class="tok-str">"tok-cmt">// class="tok-num">6

class=class="tok-str">"tok-cmt">// ragged - rows have different lengths
int[][] ragged = {
    {class="tok-num">1},
    {class="tok-num">2, class="tok-num">3},
    {class="tok-num">4, class="tok-num">5, class="tok-num">6}
};

for (int[] row : ragged) {
    for (int cell : row) {
        System.out.print(cell + " ");
    }
    System.out.println();
}

5. The java.util.Arrays Utility Class

The Arrays class provides static helpers for the common operations you would otherwise write by hand:

java
import java.util.Arrays;

int[] nums = {class="tok-num">5, class="tok-num">2, class="tok-num">8, class="tok-num">1, class="tok-num">9, class="tok-num">3};

class=class="tok-str">"tok-cmt">// print as a string
System.out.println(Arrays.toString(nums));   class=class="tok-str">"tok-cmt">// [class="tok-num">5, class="tok-num">2, class="tok-num">8, class="tok-num">1, class="tok-num">9, class="tok-num">3]

class=class="tok-str">"tok-cmt">// sort in place
Arrays.sort(nums);
System.out.println(Arrays.toString(nums));   class=class="tok-str">"tok-cmt">// [class="tok-num">1, class="tok-num">2, class="tok-num">3, class="tok-num">5, class="tok-num">8, class="tok-num">9]

class=class="tok-str">"tok-cmt">// binary search (array must be sorted)
int idx = Arrays.binarySearch(nums, class="tok-num">5);   class=class="tok-str">"tok-cmt">// class="tok-num">3

class=class="tok-str">"tok-cmt">// fill with a value
int[] zeros = new int[class="tok-num">5];
Arrays.fill(zeros, class="tok-num">0);

class=class="tok-str">"tok-cmt">// copy a range
int[] copy = Arrays.copyOf(nums, class="tok-num">10);   class=class="tok-str">"tok-cmt">// pads with class="tok-num">0 to length class="tok-num">10
int[] range = Arrays.copyOfRange(nums, class="tok-num">1, class="tok-num">4);   class=class="tok-str">"tok-cmt">// elements class="tok-num">1, class="tok-num">2, class="tok-num">3

class=class="tok-str">"tok-cmt">// compare for equality
boolean same = Arrays.equals(nums, copy);   class=class="tok-str">"tok-cmt">// false

For mutable operations like sort, the array is modified in place — the original ordering is lost.

6. Copying and Growing

Because arrays have a fixed length, growing one requires copying:

java
int[] src = {class="tok-num">1, class="tok-num">2, class="tok-num">3, class="tok-num">4, class="tok-num">5};

class=class="tok-str">"tok-cmt">// manual copy
int[] copy1 = new int[src.length + class="tok-num">3];
for (int i = class="tok-num">0; i < src.length; i++) {
    copy1[i] = src[i];
}

class=class="tok-str">"tok-cmt">// System.arraycopy - fast, native
int[] copy2 = new int[class="tok-num">10];
System.arraycopy(src, class="tok-num">0, copy2, class="tok-num">0, src.length);

class=class="tok-str">"tok-cmt">// Arrays.copyOf - the cleanest one-liner
int[] copy3 = Arrays.copyOf(src, class="tok-num">10);   class=class="tok-str">"tok-cmt">// pads with class="tok-num">0

ArrayList handles this internally: it stores elements in an array, and when that array is full it allocates a new one (typically 50% larger) and copies. So if you need variable-length storage, just use ArrayList.

7. Arrays vs ArrayList

FeatureArrayArrayList<E>
LengthFixed at creationGrows automatically
Element typeAny (primitives or references)References only (autobox primitives)
SyntaxLanguage-level []API: add, get, size
PerformanceSlightly faster, no bounds checking overhead in JITSlightly slower for primitives, but rarely the bottleneck
Best forFixed-size, performance-sensitive codeVariable-size, general-purpose storage

Exercises

  1. Create an array of the first 10 squares (1, 4, 9, …) with a for loop and print it.
  2. Sort an int[] of random values, then print it with Arrays.toString.
  3. Implement a 3x3 identity matrix as a 2-D array and print it.
  4. Copy an array of 5 elements into a new array of length 10 using Arrays.copyOf.
  5. Use Arrays.stream(arr).max() to find the maximum value.