Command Palette

Search for a command to run...

PHASE 3Beginner ~27 min· topic 10 of 11

Topic 3.10

The Arrays Utility Class

In one line

java.util.Arrays is a toolbox of ready-made static methods for arrays: print, sort, search, fill, copy, compare, and turn an array into a list or stream. Using it is shorter, faster and less buggy than writing the same loops yourself.

Think of it like this

A kitchen drawer of tools. You could cut a pizza with a kitchen knife, open a tin with a screwdriver and measure flour with a mug, but a pizza wheel, a tin opener and a measuring cup do each job faster and better. Arrays is that drawer for arrays: one tool for each common job, already tested by millions of programs.

Words you'll meet

New words in this topic, in plain English. Come back here whenever one feels fuzzy.

Utility class
A class that only holds static helper methods and is never instantiated, such as Arrays or Math.
In place
Changing the array you passed in, rather than returning a new one. Arrays.sort sorts in place.
Binary search
Finding a value in a sorted array by checking the middle and discarding the half that can't contain it, again and again.
Insertion point
The index where a missing key would go to keep the array sorted. binarySearch encodes it in its negative result.
Stable sort
A sort that keeps equal elements in their original order. Arrays.sort on objects is stable; on primitives stability doesn't matter.
Comparator
An object that decides the order of two values, used to sort in a custom way (Topic 9.10).
Fixed-size list
A list whose elements can be replaced but not added or removed. Arrays.asList returns one.
Lexicographic order
Dictionary order: compare first elements, and only if equal look at the next ones.

Step by step

01Print and compare without loops

Arrays.toString(nums) returns a readable string like [42, 7, 19]. You'll use it constantly while learning and debugging. For a 2D array, Arrays.deepToString (Topic 3.9).

Arrays.equals(a, b) is true when both arrays have the same length and equal elements in the same order. For arrays of objects it uses each element's equals method (Topic 4.8).

02Sorting: what algorithm, and what it costs

Arrays.sort(int[]) and the other primitive versions use a dual-pivot quicksort, O(n log n) on average and very fast in practice. Equal primitives are indistinguishable, so stability doesn't matter.

Arrays.sort(Object[]) (strings, records, any objects) uses TimSort, a merge sort variant that is stable and O(n log n) in the worst case, and close to O(n) on input that's already almost sorted.

Both sort in place: they change your array and return nothing. If you need the original order too, copy first: int[] sorted = nums.clone(); Arrays.sort(sorted);. Strings sort by character codes, so uppercase letters come before lowercase; pass String.CASE_INSENSITIVE_ORDER to ignore case.

Arrays.sort(a, from, to) sorts only indexes from to to - 1. Like most Java ranges, the start is included and the end is excluded.

03Binary search and its negative answer

Arrays.binarySearch(a, key) halves the search range each step, so a million elements need about 20 comparisons instead of up to a million. It only works on a sorted array; on unsorted input the answer is meaningless, and there is no error.

If found, it returns the index (with duplicates, any matching index). If not found it returns -(insertionPoint) - 1. The - 1 exists so that "not found, would go at index 0" is -1, distinct from "found at index 0".

So binarySearch([3, 7, 19, 25, 42], 20) returns -4: 20 would be inserted at index 3, and -(3) - 1 = -4. To recover the position: insertionPoint = -result - 1. How binary search works inside, and its many variants, is the DSA course's Binary Search module (/dsa/binary-search).

Binary search and its negative answerdiagram
Rendering diagram…

04Filling and copying

Arrays.fill(a, 7) sets every element to 7, useful for initialising a table with something other than 0, such as Integer.MAX_VALUE for shortest-distance tables or -1 for "not computed yet" in memoisation.

Arrays.copyOf(a, n) returns a new array of length n: shorter truncates, longer pads with default values. copyOfRange(a, from, to) returns the slice from from up to, not including, to.

Arrays.setAll(a, i -> i * i) fills each element from its index using a lambda (Topic 10.1).

05asList: a list view, not a copy

Arrays.asList(arr) returns a List backed by the array. Setting an element in the list changes the array, and changing the array changes the list. No elements are copied.

The list has the array's fixed size, so add and remove throw UnsupportedOperationException. For a normal, growable list, copy it: new ArrayList<>(Arrays.asList(arr)). For an unmodifiable list use List.of(...) (Java 9, Topic 9.11).

Remember the trap from Topic 3.5: Arrays.asList(int[]) gives a list with one element, the int[] itself.

06Java 8 and 9 additions

Arrays.stream(a) (Java 8) returns an IntStream, LongStream, DoubleStream or Stream<T>, so Arrays.stream(nums).sum() or .max() are one-liners. Streams are Phase 10. Arrays.parallelSort (Java 8) uses several CPU cores for large arrays.

Arrays.mismatch(a, b) (Java 9) returns the first index where two arrays differ, or -1 if they're equal. Arrays.compare(a, b) (Java 9) compares lexicographically and returns a negative, zero or positive number, like String.compareTo.

Try it yourself

  1. 1

    Decode binarySearch results

    On the sorted array [3, 7, 19, 25, 42], predict the result of searching for 1, 30 and 50 before running. (Insertion points 0, 4 and 5 give -1, -5 and -6.)

  2. 2

    Sort a copy, keep the original

    Modify "Print, sort and search" so it prints both the original order and the sorted order at the end. You'll need nums.clone() or Arrays.copyOf before sorting.

  3. 3

    Use fill for a memo table

    In the memoised Fibonacci of Topic 3.7, memo[n] != 0 was used to mean "computed". Rewrite it with Arrays.fill(memo, -1) and memo[n] != -1. Why is that more robust? (A legitimately computed 0 would no longer be mistaken for "not computed".)

Code & diagrams

Print, sort and search New tab
Sign in to run this example in your browser.

Expected output

before: [42, 7, 19, 3, 25]
sorted: [3, 7, 19, 25, 42]
index of 19: 2
search 20: -4 (insert at 3)
natural: [Banana, apple, pear]
ignore case: [apple, Banana, pear]
range sort: [9, 6, 7, 8, 5]
Fill, copy, compare, setAll and stream Java 8+ New tab
Sign in to run this example in your browser.

Expected output

fill: [7, 7, 7, 7]
copyOf 3: [1, 2, 3]
copyOf 7: [1, 2, 3, 4, 5, 0, 0]
copyOfRange 1..4: [2, 3, 4]
src == other: false
Arrays.equals: true
setAll: [0, 1, 4, 9, 16, 25]
sum via stream: 15
asList is a fixed-size view; mismatch and compare Java 9+ New tab
Sign in to run this example in your browser.

Expected output

array after set: [z, b, c]
list after array change: [z, b, q]
add failed: fixed-size list
copy: [z, b, q, d]
mismatch: 2
mismatch with copy: -1
a before b: true

Break it on purpose

Errors are the best teachers. Make each change, read the error, guess what went wrong, then reveal the answer.

Break #1

Add to a list from Arrays.asList

Call add on the list returned by Arrays.asList.

Main.javawhole filejava
import java.util.*;
public class Main {
    public static void main(String[] args) {
        List<Integer> list = Arrays.asList(1, 2, 3);
        list.add(4);
    }
}
terminal
$ java Main
── what you'll see ──
Exception in thread "main" java.lang.UnsupportedOperationException
at java.base/java.util.AbstractList.add(AbstractList.java:155)
at java.base/java.util.AbstractList.add(AbstractList.java:113)
at Main.main(Main.java:5)
JDK line numbers vary by version.

Break #2

Binary search an unsorted array

Call binarySearch on {5, 1, 4, 2, 3} without sorting.

Main.javawhole filejava
int[] u = {5, 1, 4, 2, 3};
System.out.println(Arrays.binarySearch(u, 1));
System.out.println(Arrays.binarySearch(u, 4));
terminal
$ java Main
── what you'll see ──
-1
2
No exception. 1 is in the array but reported missing; 4 is found only by luck.

Myth vs fact

Myth

Arrays.sort returns a sorted copy.

Fact

It sorts the array you pass, in place, and returns void. Copy first if you need the original order.

Myth

Arrays.asList copies the array into a new ArrayList.

Fact

It returns a fixed-size view backed by the array. Changes flow both ways, and add/remove throw.

Myth

binarySearch returns -1 when the key is missing.

Fact

It returns -(insertionPoint) - 1, which is -1 only when the key would go at index 0.

Pro corner

Extra depth for experienced readers. New to this? Skip it for now and come back later.

  • ▸

    Since JDK 14, the primitive dual-pivot quicksort falls back to heap sort when recursion gets too deep, guaranteeing O(n log n), and for small ranges uses insertion sort. Object sorting uses TimSort, which detects already-sorted runs; an inconsistent Comparator can make it throw IllegalArgumentException: Comparison method violates its general contract!.

  • ▸

    Arrays.equals, mismatch and fill on primitive arrays are backed by vectorised JDK code (ArraysSupport.vectorizedMismatch and intrinsics), so they're usually faster than an equivalent hand-written loop.

  • ▸

    Arrays.asList returns the private class java.util.Arrays$ArrayList, not java.util.ArrayList. It allows set and null elements; List.of (Java 9) forbids both and is truly unmodifiable. Know which one an API returns before you mutate it.

  • ▸

    Arrays.hashCode(a) is content-based and matches List.hashCode for the same elements, while a.hashCode() is identity-based. Using an array as a HashMap key therefore uses identity, a frequent bug; wrap it in a List or record (Topic 9.4).

Remember this

  1. 1

    Arrays lives in java.util, so add import java.util.Arrays;. Every method is static: you call it on the class, Arrays.sort(nums), passing the array as an argument. You never create an Arrays object.

  2. 2

    Viewing and comparing: toString(a) gives [3, 7, 19]; deepToString does the same for nested arrays. equals(a, b) compares contents (and deepEquals for nested arrays). hashCode(a) gives a content-based hash.

  3. 3

    Sorting and searching: sort(a) sorts in place in ascending order (a range version sorts part of the array). binarySearch(a, key) finds a key in a sorted array in O(log n) steps; if the key is missing it returns a negative number that encodes where it would go.

  4. 4

    Filling and copying: fill(a, v) sets every element; copyOf(a, newLength) copies and pads or truncates; copyOfRange(a, from, to) copies a slice (to excluded). setAll(a, i -> ...) (Java 8) computes each element from its index.

  5. 5

    Bridges to other APIs: asList(...) wraps an object array as a fixed-size List that writes through to the array; stream(a) (Java 8) opens a stream for sums, filters and more (Topic 10.4). Java 9 added mismatch (first differing index) and compare (dictionary order of two arrays).

  6. 6

    Each method is overloaded for every primitive type and for objects, which is why you can call Arrays.sort on an int[], a double[] or a String[]. Sorting objects uses their natural order (Comparable) or a Comparator you pass in (Topic 9.10).

Explain it without notes

01

Which algorithms does Arrays.sort use for primitives and for objects, and why the difference?

02

Explain the return value of Arrays.binarySearch when the key is not found.

03

What's the difference between Arrays.asList(arr) and new ArrayList<>(Arrays.asList(arr))?

04

Why must an array be sorted before calling binarySearch, and what happens if it isn't?

Practice

01

Given {88, 42, 95, 61, 73}, print the scores sorted, the lowest, the highest and the median, using Arrays methods.

02

Write a program that checks whether two words are anagrams by sorting their characters: convert with toCharArray(), sort both, compare with Arrays.equals. Test "listen"/"silent" and "java"/"lava".

03

Given the sorted array {10, 20, 30, 40}, use binarySearch to insert 25 at the correct position, producing a new array [10, 20, 25, 30, 40].

Trade-offs

  • ↔

    Arrays methods are tested, optimised and short, but they work on fixed-size arrays. Once you need to add and remove elements, move to collections (Phase 9), which offer similar helpers in Collections and List.

  • ↔

    Sorting once (O(n log n)) and then binary searching many times (O(log n) each) beats repeated linear searches, but if you only search once, a single linear scan (O(n)) is cheaper than sorting.

  • ↔

    Arrays.asList is a cheap view with no copying, but its fixed size and write-through behaviour surprise people. Copy when you need independence.

Done when you can

  • Done when you can print, compare, fill and copy arrays with Arrays instead of loops.

  • Done when you can sort whole arrays and ranges, and sort strings case-insensitively.

  • Done when you can decode a negative binarySearch result into an insertion point.

  • Done when you can explain why Arrays.asList lists can't grow and how to get one that can.

  • Done when you know which sort algorithm is used for primitives vs objects and why.