☕ Java

Arrays Class

The java.util.Arrays class is a utility class containing static methods for array manipulation. It provides sorting, searching, comparison, copying, filling, converting to string, and stream operations. Arrays is the Swiss army knife for array operations in Java — before writing any array manipulation loop, check whether Arrays already provides it. This entry covers every major Arrays method with its semantics, performance characteristics, and practical use cases, including the lesser-known but powerful methods like Arrays.mismatch() and Arrays.compare().

Copying Arrays

Arrays.copyOf() creates a new array of a specified length, copying elements from the source. If the new length is larger than the source, the extra elements are filled with the type's default value (0 for int, null for references). If the new length is smaller, only the first newLength elements are copied — it acts as a truncation. This is the standard way to grow an array: copy to a larger size. Arrays.copyOfRange() copies a sub-range of the source array into a new array. The range is [from, to) — from inclusive, to exclusive. If to exceeds the source array's length, the extra positions are filled with defaults. This is useful for extracting a portion of an array without modifying the original. System.arraycopy() is the low-level array copying primitive that Arrays.copyOf() and Arrays.copyOfRange() use internally. It copies a specified number of elements from a source array starting at a given offset to a destination array starting at a given destination offset. System.arraycopy() is faster than any manual copy loop because it uses native memory copying operations, and it correctly handles overlapping source and destination ranges within the same array (essential for shifting elements during insertion and deletion).
Java
// ── Arrays.copyOf() — copy with optional resize ───────────────────────
int[] original = {1, 2, 3, 4, 5};

int[] exact     = Arrays.copyOf(original, 5);  // same size: [1,2,3,4,5]
int[] truncated = Arrays.copyOf(original, 3);  // shorter:   [1,2,3]
int[] extended  = Arrays.copyOf(original, 8);  // longer:    [1,2,3,4,5,0,0,0]

System.out.println(Arrays.toString(exact));     // [1, 2, 3, 4, 5]
System.out.println(Arrays.toString(truncated)); // [1, 2, 3]
System.out.println(Arrays.toString(extended));  // [1, 2, 3, 4, 5, 0, 0, 0]

// ── Growing an array ──────────────────────────────────────────────────
int[] arr = new int[5];
int   size = 0;

// Simulate adding beyond capacity (like ArrayList does internally)
for (int i = 0; i < 10; i++) {
    if (size == arr.length) {
        arr = Arrays.copyOf(arr, arr.length * 2);  // double capacity
    }
    arr[size++] = i * 10;
}
System.out.println(Arrays.toString(Arrays.copyOf(arr, size)));
// [0, 10, 20, 30, 40, 50, 60, 70, 80, 90]

// ── Arrays.copyOfRange() — extract sub-array ──────────────────────────
int[] data = {10, 20, 30, 40, 50, 60, 70};

int[] middle = Arrays.copyOfRange(data, 2, 5);  // indices 2,3,4
System.out.println(Arrays.toString(middle));     // [30, 40, 50]

int[] tail = Arrays.copyOfRange(data, 4, data.length); // from index 4 to end
System.out.println(Arrays.toString(tail));       // [50, 60, 70]

// ── System.arraycopy() — fast low-level copy ──────────────────────────
int[] src  = {1, 2, 3, 4, 5};
int[] dest = new int[8];

System.arraycopy(src, 1, dest, 2, 3);
// Copies 3 elements from src starting at index 1
// to dest starting at index 2
System.out.println(Arrays.toString(dest));  // [0, 0, 2, 3, 4, 0, 0, 0]

// ── Shift elements right — make room for insertion ────────────────────
int[] buf  = {10, 20, 30, 40, 50, 0, 0};
int   insertPos = 2;
int   length    = 5;   // active elements

// Shift elements from insertPos to length-1 one position right
System.arraycopy(buf, insertPos, buf, insertPos + 1, length - insertPos);
buf[insertPos] = 99;
System.out.println(Arrays.toString(buf));   // [10, 20, 99, 30, 40, 50, 0]

Filling, Equality, and String Conversion

Arrays.fill() sets every element (or a sub-range) of an array to a specified value. It is faster than a manual loop and clearly communicates intent. Common uses include initializing all elements to a sentinel value, resetting an array between uses, and initializing a 2D array's rows to a specific value by calling fill() on each row. Arrays.equals() performs element-wise comparison of two arrays. It returns true only if both arrays have the same length and all corresponding elements are equal (using == for primitives and .equals() for objects). The vanilla == operator on arrays compares references (are they the same object?), not content — a common source of bugs. Arrays.deepEquals() handles multidimensional arrays recursively, comparing the contents of nested arrays rather than comparing the nested array references. Arrays.toString() converts an array to a human-readable string in the format [e0, e1, e2, ...]. It is the standard way to print an array for debugging — the default Object.toString() on an array produces an unreadable type-prefix and hash code. Arrays.deepToString() handles multidimensional arrays, producing nested brackets that reflect the structure.
Java
// ── Arrays.fill() — set all elements to a value ──────────────────────
int[]    zeros = new int[5];
Arrays.fill(zeros, 0);          // [0, 0, 0, 0, 0] — same as default

int[]    nines = new int[5];
Arrays.fill(nines, 9);          // [9, 9, 9, 9, 9]

boolean[] flags = new boolean[4];
Arrays.fill(flags, true);       // [true, true, true, true]

String[] sentinels = new String[3];
Arrays.fill(sentinels, "empty"); // [empty, empty, empty]

// ── Partial fill — sub-range ──────────────────────────────────────────
int[] data = {1, 2, 3, 4, 5, 6, 7};
Arrays.fill(data, 2, 5, 0);     // fill indices [2, 5) with 0
System.out.println(Arrays.toString(data));  // [1, 2, 0, 0, 0, 6, 7]

// ── Initialise rows of a 2D array ─────────────────────────────────────
int[][] grid = new int[3][4];
for (int[] row : grid) Arrays.fill(row, -1);
System.out.println(Arrays.deepToString(grid));
// [[-1, -1, -1, -1], [-1, -1, -1, -1], [-1, -1, -1, -1]]

// ── Arrays.equals() — content comparison ─────────────────────────────
int[] a = {1, 2, 3};
int[] b = {1, 2, 3};
int[] c = {1, 2, 4};

System.out.println(a == b);              // false — different objects
System.out.println(Arrays.equals(a, b)); // true  — same content
System.out.println(Arrays.equals(a, c)); // false — different content

// ── Arrays.deepEquals() — nested arrays ──────────────────────────────
int[][] m1 = {{1,2},{3,4}};
int[][] m2 = {{1,2},{3,4}};

System.out.println(Arrays.equals(m1, m2));     // false — compares row refs
System.out.println(Arrays.deepEquals(m1, m2)); // true  — compares contents

// ── Arrays.toString() and Arrays.deepToString() ───────────────────────
int[]    arr1D = {5, 2, 8, 1, 9};
int[][]  arr2D = {{1,2,3},{4,5,6}};
int[][][] arr3D = {{{1,2},{3,4}},{{5,6},{7,8}}};

System.out.println(arr1D);                       // [I@7852e922 — useless!
System.out.println(Arrays.toString(arr1D));      // [5, 2, 8, 1, 9]
System.out.println(Arrays.deepToString(arr2D));  // [[1, 2, 3], [4, 5, 6]]
System.out.println(Arrays.deepToString(arr3D));  // [[[1, 2], [3, 4]], [[5, 6], [7, 8]]]

Sorting and Searching

Arrays.sort() and Arrays.binarySearch() are the core sorting and searching methods covered in the Array Sorting and Array Searching entries. Arrays provides additional support through Arrays.parallelSort() for parallel multi-core sorting, range-based overloads for both sort and search that operate on sub-arrays, and Comparator-accepting overloads for custom sort orders on object arrays. Arrays.setAll() and Arrays.parallelSetAll() initialize array elements using an IntUnaryOperator (a function from index to value). These are more expressive than fill() when the initial values depend on the index and more parallel-friendly than a fill loop. Arrays.parallelPrefix() applies a prefix sum (or any associative binary operation) to the array in parallel, computing the running aggregate in O(log n) time using a parallel scan algorithm.
Java
// ── Arrays.setAll() — initialize by index ────────────────────────────
int[] squares = new int[10];
Arrays.setAll(squares, i -> i * i);   // each element = index²
System.out.println(Arrays.toString(squares));
// [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

double[] sines = new double[8];
Arrays.setAll(sines, i -> Math.sin(i * Math.PI / 4));
// [sin(0), sin(π/4), sin(π/2), sin(3π/4), ...]

// ── Arrays.parallelSetAll() — parallel initialization ─────────────────
int[] large = new int[1_000_000];
Arrays.parallelSetAll(large, i -> i % 100);   // fills in parallel

// ── Arrays.parallelPrefix() — running aggregate ───────────────────────
int[] values = {1, 2, 3, 4, 5};
Arrays.parallelPrefix(values, Integer::sum);  // prefix sum
System.out.println(Arrays.toString(values));
// [1, 3, 6, 10, 15]  — running total

int[] products = {1, 2, 3, 4, 5};
Arrays.parallelPrefix(products, (a, b) -> a * b);  // prefix product
System.out.println(Arrays.toString(products));
// [1, 2, 6, 24, 120]

// ── Sort + search combination ─────────────────────────────────────────
int[] unsorted = {15, 3, 42, 8, 27, 19};
Arrays.sort(unsorted);
System.out.println(Arrays.toString(unsorted));  // [3, 8, 15, 19, 27, 42]

int idx = Arrays.binarySearch(unsorted, 19);
System.out.println("Found at: " + idx);  // 3

// ── Sort object array with custom order, then binary search ───────────
String[] words = {"banana", "apple", "fig", "cherry", "date"};
Comparator<String> byLength = Comparator.comparingInt(String::length)
    .thenComparing(Comparator.naturalOrder());

Arrays.sort(words, byLength);
System.out.println(Arrays.toString(words));
// [fig, apple, date, banana, cherry] — sorted by length, then alpha

int pos = Arrays.binarySearch(words, "date", byLength);
System.out.println("date at: " + pos);  // valid index

Comparison, Mismatch, and Stream Conversion

Arrays.compare() performs lexicographic comparison of two arrays — like String.compareTo() but for arrays of any type. It compares element by element; the first differing element determines the result. If all common elements are equal, the shorter array is considered "less than" the longer one. Arrays.compare() is useful for sorting arrays of arrays or building composite comparison logic. Arrays.mismatch() returns the index of the first element that differs between two arrays. If the arrays are equal up to the length of the shorter one, it returns the length of the shorter array. If the arrays are completely equal, it returns -1. Arrays.mismatch() is more informative than Arrays.equals() when you need to know where the arrays diverge, not just whether they diverge. Arrays.stream() converts an array to a stream for functional processing. It has overloads for int[], long[], double[] that return specialised IntStream, LongStream, and DoubleStream respectively — avoiding boxing overhead. A range overload processes only a sub-array. The stream can then be used for any Stream operation: filter, map, reduce, collect, sorted, distinct, and more.
Java
// ── Arrays.compare() — lexicographic comparison ──────────────────────
int[] a = {1, 2, 3, 4};
int[] b = {1, 2, 4, 4};
int[] c = {1, 2, 3};      // prefix of a

System.out.println(Arrays.compare(a, b));  // negative: a < b (3 < 4 at index 2)
System.out.println(Arrays.compare(b, a));  // positive: b > a
System.out.println(Arrays.compare(a, a));  // 0: equal
System.out.println(Arrays.compare(c, a));  // negative: c < a (shorter)

// ── Sorting arrays of arrays ──────────────────────────────────────────
int[][] arrays = {{3,1},{1,2},{1,1},{2,5}};
Arrays.sort(arrays, Arrays::compare);    // lexicographic order
for (int[] arr : arrays) System.out.println(Arrays.toString(arr));
// [1, 1]
// [1, 2]
// [2, 5]
// [3, 1]

// ── Arrays.mismatch() — find first difference ─────────────────────────
int[] x = {1, 2, 3, 4, 5};
int[] y = {1, 2, 9, 4, 5};
int[] z = {1, 2, 3, 4, 5};  // identical to x

System.out.println(Arrays.mismatch(x, y));  // 2 — first difference at index 2
System.out.println(Arrays.mismatch(x, z));  // -1 — arrays are equal

// ── Find common prefix length ─────────────────────────────────────────
int[] p = {1, 2, 3, 4, 5};
int[] q = {1, 2, 3, 9, 9};
int mismatchAt = Arrays.mismatch(p, q);
System.out.println("Common prefix length: " + mismatchAt);  // 3

// ── Arrays.stream() — functional pipeline ────────────────────────────
int[]    nums    = {3, 1, 4, 1, 5, 9, 2, 6, 5};
String[] words   = {"hello", "java", "stream", "arrays"};

// IntStream — no boxing
int    sum     = Arrays.stream(nums).sum();         // 36
double avg     = Arrays.stream(nums).average().orElse(0); // 4.0
int    max     = Arrays.stream(nums).max().getAsInt();    // 9
long   distinct = Arrays.stream(nums).distinct().count(); // 7

// Filter, map, collect
int[] evens = Arrays.stream(nums)
    .filter(n -> n % 2 == 0)
    .toArray();
System.out.println(Arrays.toString(evens));  // [4, 2, 6]

// String stream
String longestWord = Arrays.stream(words)
    .max(Comparator.comparingInt(String::length))
    .orElse("");
System.out.println(longestWord);  // "stream"

// ── Range stream — process only a sub-range ───────────────────────────
int[] data = {10, 20, 30, 40, 50, 60, 70};
int rangeSum = Arrays.stream(data, 2, 5).sum();  // indices 2,3,4
System.out.println(rangeSum);   // 30 + 40 + 50 = 120

// ── Convert stream back to array ─────────────────────────────────────
int[] sorted = Arrays.stream(nums)
    .distinct()
    .sorted()
    .toArray();
System.out.println(Arrays.toString(sorted));  // [1, 2, 3, 4, 5, 6, 9]

Related Topics in Arrays

Array Basics
An array in Java is a fixed-size, ordered collection of elements of the same type stored in a contiguous block of memory. Once created, the size of an array cannot change. Arrays are the simplest and most fundamental data structure in Java — they underlie many higher-level collections and provide direct, indexed access to elements in constant time O(1). Every array in Java is an object, inherits from java.lang.Object, and can hold either primitives or references.
One-Dimensional Array
A one-dimensional array is a linear sequence of elements of the same type, accessed by a single integer index. It is the simplest array form in Java and the foundation for understanding multidimensional arrays and collection classes. One-dimensional arrays are used to store and process lists of values — student grades, product prices, daily temperatures, character sequences — any time you need to work with a fixed-size ordered collection of homogeneous data.
Two-Dimensional Array
A two-dimensional array in Java is an array of arrays — each element of the outer array is itself a one-dimensional array. It is used to represent tabular data with rows and columns: matrices, game boards, spreadsheet grids, pixel buffers, and any data that is naturally organised in two dimensions. In Java, a 2D array is declared with two sets of brackets and accessed with two indices: array[row][column].
Multidimensional Array
A multidimensional array in Java is an array with more than two dimensions — an array of arrays of arrays, and so on. While two-dimensional arrays suffice for most programming tasks, three-dimensional arrays are used for spatial data (x, y, z coordinates of a 3D grid), volumetric data (layers, rows, columns), RGB pixel buffers, and scientific computations involving tensors. Java supports arbitrary dimensionality, though arrays beyond three dimensions are rare in practice.