Java Arrays
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:
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:
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:
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):
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:
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:
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
| Feature | Array | ArrayList<E> |
|---|---|---|
| Length | Fixed at creation | Grows automatically |
| Element type | Any (primitives or references) | References only (autobox primitives) |
| Syntax | Language-level [] | API: add, get, size |
| Performance | Slightly faster, no bounds checking overhead in JIT | Slightly slower for primitives, but rarely the bottleneck |
| Best for | Fixed-size, performance-sensitive code | Variable-size, general-purpose storage |
Exercises
- Create an array of the first 10 squares (1, 4, 9, …) with a
forloop and print it. - Sort an
int[]of random values, then print it withArrays.toString. - Implement a 3x3 identity matrix as a 2-D array and print it.
- Copy an array of 5 elements into a new array of length 10 using
Arrays.copyOf. - Use
Arrays.stream(arr).max()to find the maximum value.