Skip to content
Ameen Abozaid
PublishedBEG-015-L06

Arrays utility class

  • Lesson 6 of 8
  • 10 min read
  • Beginner
On This Lesson 11 topics

Lesson Overview

By now you have written a loop to print an array, a loop to find the largest element, and perhaps a loop to copy. Java ships ready-made versions of these chores in one place: the java.util.Arrays class, a toolbox full of static helper methods for arrays.

In locker terms: instead of walking along the row yourself every time, you call a caretaker who can read the whole row out loud (toString), put the lockers in order (sort), fill them all with the same item (fill), build you a duplicate row (copyOf), and tell you whether two rows hold the same things (equals).

This lesson also fixes two debts from earlier: Lesson 1 said "a real copy comes later", and printing an array with println(arr) gives a strange code instead of the values.

Why this matters: knowing the standard helper beats rewriting it. Tested library code is shorter, clearer, and less likely to hide an off-by-one error than your own loop.

This lesson builds on arrays (Lessons 1-3) and on references (BEG-009).

Learning Objectives

By the end of this lesson you will be able to:

  • Import java.util.Arrays and call its static methods.
  • Print an array readably with Arrays.toString, and a 2D array with Arrays.deepToString.
  • Sort an array in place with Arrays.sort.
  • Make a real copy with Arrays.copyOf and Arrays.copyOfRange, including growing or shrinking.
  • Fill an array with one value, and compare two arrays by content with Arrays.equals.
  • Explain why b = a and a == b do not copy and do not compare contents.
  • Explain why a copy of a 2D array needs one more step.

Written Explanation

Import first

Arrays lives in the package java.util, so the file starts with:

java
import java.util.Arrays;

All its methods are static: you call them on the class, as in Arrays.sort(a), not on an array object.

Printing: toString

System.out.println(a) for an array prints the type and a hash code, such as [I@6d06d69c, because an array does not define a readable text form of its own. The text and number after @ are not useful. Use:

java
System.out.println(Arrays.toString(a));   // [3, 1, 2]

For a 2D array, toString would show the inner arrays as codes too, because the elements are arrays. Arrays.deepToString(grid) goes into the nested arrays and prints [[1, 2], [3, 4]].

Sorting: sort

Arrays.sort(a) rearranges a in place into ascending order. For int[] the order is numeric; for String[] it is alphabetical by character code, so all upper-case letters come before lower-case ones, which surprises many beginners. The method returns nothing (void), so the original order is lost. If you still need it, sort a copy. An overload Arrays.sort(a, from, to) sorts only the positions from from up to, but not including, to, and throws an exception when the range is invalid.

Copying: copyOf and copyOfRange

java
int[] c = Arrays.copyOf(a, a.length);       // same size
int[] bigger = Arrays.copyOf(a, 5);         // longer: extra slots are 0
int[] smaller = Arrays.copyOf(a, 2);        // shorter: cut off the end
int[] part = Arrays.copyOfRange(a, 1, 3);   // positions 1 and 2 (end excluded)

The result is a new array. When it is longer, the new slots hold the default value (0, false, or null). This is also how you "grow" an array: create a larger copy and assign it to your variable. copyOfRange again includes the start and excludes the end, as substring does.

Filling: fill

Arrays.fill(a, 7) sets every element to 7. It is shorter than a loop and clearly states the intent, for example to mark every seat as free or to start every counter at -1.

Comparing: equals

Two array variables compared with == ask "are they the same array object?". Calling a.equals(b) on an array does the same, because arrays do not override it. To ask "do they hold the same values in the same order?", use:

java
Arrays.equals(x, y)      // compares length and every element

For nested arrays there is Arrays.deepEquals.

Copies of copies: 2D arrays are shallow

A 2D array is an array of row pointers (Lesson 3). Arrays.copyOf(grid, grid.length) copies the outer row of pointers; the inner rows are still shared by the original and the copy. A change to copy[0][0] therefore also changes grid[0][0]. For an independent copy, copy every row too:

java
int[][] deep = new int[grid.length][];
for (int r = 0; r < grid.length; r++) {
    deep[r] = Arrays.copyOf(grid[r], grid[r].length);
}

The same caution applies to an array of any other reference type: the copy holds the same objects (for String, which is immutable, that is harmless).

Examples

Example 1: print, sort, copy, fill (simple)

java
import java.util.Arrays;

public class Ex1 {
    public static void main(String[] args) {
        int[] a = {3, 1, 2};
        System.out.println(Arrays.toString(a));
        Arrays.sort(a);
        System.out.println(Arrays.toString(a));
        int[] b = a;
        int[] c = Arrays.copyOf(a, a.length);
        b[0] = 100;
        System.out.println(a[0] + " " + c[0]);
        int[] zeros = new int[4];
        Arrays.fill(zeros, 7);
        System.out.println(Arrays.toString(zeros));
        System.out.println(Arrays.toString(Arrays.copyOf(a, 5)));
        System.out.println(Arrays.toString(Arrays.copyOf(a, 2)));
        System.out.println(Arrays.toString(Arrays.copyOfRange(zeros, 1, 3)));
        String[] words = {"pear", "apple", "fig"};
        Arrays.sort(words);
        System.out.println(Arrays.toString(words));
    }
}

Output (compiled and run with JDK 21):

text
[3, 1, 2]
[1, 2, 3]
100 1
[7, 7, 7, 7]
[100, 2, 3, 0, 0]
[100, 2]
[7, 7]
[apple, fig, pear]

Writing b[0] = 100 changed a[0] (same array) but not c[0] (the real copy). copyOf(a, 5) padded with zeros and copyOf(a, 2) cut the array short. The words came out alphabetical.

Example 2: comparing arrays and sorting a copy (practical)

java
import java.util.Arrays;

public class Ex2 {
    public static void main(String[] args) {
        int[] x = {1, 2, 3};
        int[] y = {1, 2, 3};
        System.out.println(x == y);
        System.out.println(x.equals(y));
        System.out.println(Arrays.equals(x, y));
        int[] original = {5, 9, 1, 7};
        int[] sorted = Arrays.copyOf(original, original.length);
        Arrays.sort(sorted);
        System.out.println("smallest " + sorted[0] + ", largest " + sorted[sorted.length - 1]);
        System.out.println(Arrays.toString(original));
        System.out.println(original.toString().startsWith("[I@"));
    }
}

Output:

text
false
false
true
smallest 1, largest 9
[5, 9, 1, 7]
true

The arrays x and y hold the same numbers but are two different objects, so == and .equals say false, and only Arrays.equals says true. After sorting a copy, the smallest and largest come from the two ends, and the original order is intact. The last line confirms that an array's own toString() begins with the type code [I@.

Example 3: shallow and deep copies of a grid (realistic)

java
import java.util.Arrays;

public class Ex3 {
    public static void main(String[] args) {
        int[][] grid = {{1, 2}, {3, 4}};
        System.out.println(Arrays.toString(grid).startsWith("[[I@"));
        System.out.println(Arrays.deepToString(grid));
        int[][] shallow = Arrays.copyOf(grid, grid.length);
        shallow[0][0] = 99;
        System.out.println(grid[0][0]);
        int[][] deep = new int[grid.length][];
        for (int r = 0; r < grid.length; r++) {
            deep[r] = Arrays.copyOf(grid[r], grid[r].length);
        }
        deep[1][1] = -1;
        System.out.println(Arrays.deepToString(grid));
        System.out.println(Arrays.deepToString(deep));
        int[] data = {4, 2};
        Arrays.sort(data, 0, 3);
    }
}

Output (JDK-internal trace lines left out):

text
true
[[1, 2], [3, 4]]
99
[[99, 2], [3, 4]]
[[99, 2], [3, -1]]
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Array index out of range: 3
	at Ex3.main(Ex3.java:19)

Arrays.toString on a grid prints row codes, deepToString prints the values. Changing the shallow copy changed the original (99), because the rows are shared. The deep copy has its own rows, so the later change to deep[1][1] left grid untouched, and the original still shows the earlier 99. The last line asks sort for a range ending at 3 in a length-2 array, which the method rejects with an ArrayIndexOutOfBoundsException.

Backend Insight

Real programs take arrays from callers they do not control. Two habits from this lesson matter in production:

  • Defensive copies. If a method stores or returns an array that belongs to another part of the program, copy it. Otherwise a later change in one place silently changes the data in another. Arrays.copyOf is the one-line way to do it.
  • Do not sort what you do not own. Arrays.sort changes the array it is given. Sorting a caller's array changes the caller's data. Sort a copy unless changing the order is the whole point of your method.

Searching and sorting data is a core part of backend work, and databases do it for you with ORDER BY. Sorting in Java is for data already in memory.

Common Mistakes

Mistake 1: Printing an array with println(a)

You get a code like [I@6d06d69c. Use Arrays.toString(a), or Arrays.deepToString(g) for a grid.

Mistake 2: Thinking b = a copies

It creates a second name for the same array. Use Arrays.copyOf for a copy.

Mistake 3: Comparing arrays with == or .equals

Both ask whether they are the same object. Use Arrays.equals(a, b) to compare contents.

Mistake 4: Expecting sort to return the sorted array

Arrays.sort(a); sorts a and returns nothing. Writing int[] s = Arrays.sort(a); does not compile.

Mistake 5: Believing a copy of a grid is independent

Arrays.copyOf on a 2D array shares the rows. Copy each row as well.

Mistake 6: Forgetting the import

Without import java.util.Arrays;, the compiler reports that it cannot find Arrays.

Exercises

Try each exercise yourself before opening the solutions.

Level A: Foundation

A1. Which statement prints [4, 8, 15] for int[] a = {4, 8, 15};: println(a) or println(Arrays.toString(a))?

Show solution A1

A1. System.out.println(Arrays.toString(a)). The plain println(a) prints a type code and hash.

A2. What does Arrays.copyOf(new int[]{1, 2, 3}, 5) produce?

Show solution A2

A2. [1, 2, 3, 0, 0]: the new longer array is padded with the default value for int.

A3. After int[] a = {9, 3, 6}; Arrays.sort(a);, what is a[0]?

Show solution A3

A3. 3. The array becomes {3, 6, 9}.

Level B: Application

B1. You have int[] scores = {70, 90, 80} and need the highest value without changing the order of scores. Write the code using Arrays.

Show solution B1

B1.

java
int[] copy = Arrays.copyOf(scores, scores.length);
Arrays.sort(copy);
int highest = copy[copy.length - 1];

scores keeps its order because only the copy was sorted. (This assumes at least one element.)

B2. What do these print?

java
int[] p = {1, 2};
int[] q = {1, 2};
int[] r = p;
System.out.println((p == q) + " " + (p == r) + " " + Arrays.equals(p, q));
Show solution B2

B2. It prints false true true. p and q are different arrays with equal contents, p and r are the same array, and Arrays.equals compares contents.

B3. Use Arrays.fill and Arrays.copyOfRange to build {0, 0, 5, 5} from a 6-element array that you first fill with 5 (the answer is two statements after the fill).

Show solution B3

B3.

java
int[] a = new int[6];
Arrays.fill(a, 5);
int[] b = Arrays.copyOfRange(a, 0, 4);   // {5, 5, 5, 5}
b[0] = 0;
b[1] = 0;                                // {0, 0, 5, 5}

Several equivalent solutions are possible; the point is that copyOfRange gives a new, independent array that you may change.

Level C: Challenge

C1. Write static int[] addOne(int[] a, int value) that returns a new array one element longer, with value at the end, leaving a unchanged. Use Arrays.

Show solution C1

C1.

java
static int[] addOne(int[] a, int value) {
    int[] result = Arrays.copyOf(a, a.length + 1);
    result[result.length - 1] = value;
    return result;
}

The extra slot from copyOf is the new last position, and a is never touched.

C2. A method static int[][] copyGrid(int[][] g) must return an independent copy. Write it, and explain which line would be wrong if you replaced the loop body with deep[r] = g[r];.

Show solution C2

C2.

java
static int[][] copyGrid(int[][] g) {
    int[][] deep = new int[g.length][];
    for (int r = 0; r < g.length; r++) {
        deep[r] = Arrays.copyOf(g[r], g[r].length);
    }
    return deep;
}

With deep[r] = g[r]; the rows would be shared with the original, so changing copy[0][0] would still change g[0][0]: the result would look like a copy but would not be independent.

Mini Challenge

Write a small "top three" program. Given an int[] of at least three scores (for example {62, 91, 75, 88, 49, 91}), print the three highest values from highest to lowest without changing the original array, and print the original array afterwards to prove it is unchanged. Use Arrays.copyOf, Arrays.sort, and Arrays.toString. What does your program do when the array has fewer than three elements?

Check your work: you sorted a copy, you indexed from length - 1 downwards, and you handled the short array instead of crashing.

Summary & Next Lesson

Key takeaways

  • Arrays is a toolbox of static helpers; import java.util.Arrays first.
  • Arrays.toString (and deepToString for grids) prints readable contents; println(arr) prints a code.
  • Arrays.sort sorts in place and returns nothing; sort a copy when you must keep the original order.
  • Arrays.copyOf and copyOfRange create real copies and can grow (zero-padded) or shrink; b = a copies only the pointer.
  • Compare contents with Arrays.equals; == and .equals on arrays compare identity.
  • A copy of a 2D array shares its rows unless you copy each row.

Next lesson

The next lesson, "Demo: student-grade manager with arrays", puts arrays, loops, methods, and Strings together to build the core of the module lab.

Self-check

  1. How do you print an array readably?
  2. Does Arrays.sort(a) return a new array?
  3. How do you make a real copy of a?
  4. How do you compare two arrays by content?
  5. Why is Arrays.copyOf(grid, grid.length) not an independent copy of a 2D array?
Show answers
  1. Arrays.toString(a).
  2. No. It sorts a in place and returns nothing.
  3. int[] c = Arrays.copyOf(a, a.length);
  4. Arrays.equals(a, b).
  5. It copies the outer array of row pointers only, so the original and the copy still share the same inner rows.

References

  • Oracle, Arrays class, Java SE 21 API. It supports: toString, deepToString, in-place ascending sort (with a range form that throws ArrayIndexOutOfBoundsException for an invalid range), copyOf (truncates or pads with default values), copyOfRange (end excluded), fill, equals, and deepEquals.
  • Oracle, Java Language Specification SE 21, chapter 10: Arrays. It supports: a multi-dimensional array is an array of references to sub-arrays, and cloning is shallow with respect to them.
  • Not verified from a primary page: that String[] sorts upper-case before lower-case (a run with JDK 21 gave [Zebra, apple, banana], consistent with character-code order), and the exact text of the [I@... form (the examples confirm its start by running JDK 21). All outputs were produced by running the code with JDK 21.

Practice

Apply this lesson with the module's lab, exercises and quiz.

Lab and exercises Quiz

Marking a lesson complete is optional and you can undo it any time. Your progress stays in this browser.

Continue to next lesson

Type to search levels, phases, modules and lessons.