Concepts / Standard Array Methods

Standard Array Methods

Arrays.copyOf(list, lengthOfCopy) returns a new array of the requested length, copying items from the original and filling any extra positions with default values

  • Programming

Predicting What a Copy Produces

Suppose you have an array and you want a second array with the same values. It seems like a task Java should already handle, and it does. The useful question is what you actually get when you ask for a copy, and where the copy and the original start to differ. Before reading on, make a prediction about the program below.

What do you think happens?

What does the second line print when the program runs: [1, 2, 3, 0, 0] or [1, 2, 3]?

  • [1, 2, 3, 0, 0]

  • [1, 2, 3]

  • An error, because the copy is longer than the original

Reveal answer
Answer:

[1, 2, 3, 0, 0]

Arrays.copyOf builds a new array of length 5. The three original items are copied into the first three positions, and the two extra positions receive the default value 0 for an int array.

Where the Array Methods Live

Java includes standard array-processing methods so that common jobs like copying do not have to be hand-written each time. Without them, copying an array means creating a new array of the same size and writing a loop that copies each element across, one index at a time. That works, but every programmer who needs a copy would write the same loop again.

Definition

The standard array-processing methods are static methods defined in a class named Arrays, which lives in the package java.util. The method that copies arrays is Arrays.copyOf.

Notice the naming pattern. The method belongs to the class Arrays, not to an individual array variable. Whether the array is small or large, the method is reached through the same class name, and the array you want to process is passed in as an argument. A call to copyOf takes two things: the array to copy, and the length you want the result to have. The call returns a new array of that length, filled with items copied from the original.

java
Output
[1, 2, 3, 0, 0]
[1, 2, 3]
Notes on the code
  • import java.util.Arrays brings the Arrays class into scope
  • Arrays.copyOf(original, 5) is a static call: the class name comes first, then the method name, then the arguments
  • original.clone() is an instance call made on the array itself, with no length argument
  • Arrays.toString is used only to display the contents of each array

Tracing a Copy Step by Step

The requested length controls how many items can be copied. When the requested length is larger than the original, the extra positions in the new array receive default values: zero for numeric arrays, null for object arrays, and so on. When the requested length is smaller than or equal to the original, only as many items are copied as will fit. The length argument is the one thing that decides the size of the result, so the same method can produce a bigger array, a smaller array, or an exact duplicate.

1index 01index 02index 12index 13index 23index 20default value0default valuecopiedcopiedcopied
When copyOf builds a five-item array from a three-item array, which original positions land where, and what fills the extra slots?
Worked example

Copying a Score Array to a Longer Length

Start with int[] scores = {10, 20, 30}. Predict the contents of the array returned by Arrays.copyOf(scores, 4), then check what happens to scores itself.

  1. 1
    Step 1: Read the arguments

    The first argument is the array to copy, scores. The second argument is the requested length, 4, which is larger than scores.length, which is 3.

  2. 2
    Step 2: Copy the matching positions

    Positions 0, 1, and 2 of the original are copied into positions 0, 1, and 2 of the new array, giving 10, 20, and 30.

  3. 3
    Step 3: Fill the extra position

    Position 3 of the new array has no original item to copy from, so it receives the default value 0 for an int array.

  4. 4
    Step 4: Check the original

    copyOf does not change its input. The scores array still has length 3 and still holds 10, 20, 30.

  5. 5
    Step 5: Keep the result

    Calling Arrays.copyOf(scores, 4) without assigning its result computes a copy that is then discarded. The result must be stored in a variable, for example int[] bigger = Arrays.copyOf(scores, 4).

Result

bigger holds [10, 20, 30, 0]. scores is unchanged and still holds [10, 20, 30].

Resizing by Doubling and Halving

The same call that makes a copy can change how much room an array has. This matters when an array is only partly used, for example a list of players where only the first few positions hold real entries. Passing twice the current length produces a larger array in one line, which doubles the space available. Passing half the length produces a smaller array, which is useful when most of the space would otherwise sit empty.

java
Output
[10, 20, 30, 40, 0, 0, 0, 0]
[10, 20]
Notes on the code
  • scores.length * 2 requests twice the current length, so the new array has room for four more items
  • scores.length / 2 requests half the length, so only the first two items fit
  • Each call returns a new array, which is stored in its own variable
10index 010index 020index 120index 130index 2 dropped40index 3 droppedkeptkept
How do the length and contents of scores change when Arrays.copyOf(scores, scores.length / 2) runs?

Shrinking works by copying as many items as fit and dropping the rest. Consider removing an entry from a list of players: one approach is to copy the last filled entry into the position being removed and reduce the count of players. If the count falls below a quarter of the array's capacity, the array can be cut in half with copyOf. Arrays.copyOf does not treat the surviving entries specially. It copies as many items as fit, so the entries that survive the halving are kept and the spare positions are dropped.

Choosing Between copyOf and clone

When you want a simple copy with exactly the same size as the original, there is a shorter route. Every array has an instance method named clone() that makes a copy of the array. You call it on the array itself rather than passing the array to a static method. clone() has no length argument, so it cannot resize. If you need a different size, Arrays.copyOf is the tool to use. If you need only a same-size copy, clone() is the more direct expression of that intent.

FeatureArrays.copyOfclone()
Kind of methodStatic method in the Arrays classInstance method on the array itself
Call formArrays.copyOf(list, length)list.clone()
Length argumentRequired, and sets the size of the resultNone, so the copy is the same size
Can resizeYes, larger or smallerNo
ResultA new, separate arrayA new, separate array

Two ways to create a copy of an array in Java

Copying Arrays of Objects

The copying behavior described so far applies to arrays of numbers. Arrays of objects behave differently in one important way. The Arrays class contains a copyOf method for each primitive type and one for objects. When an array of objects is copied, only the references to the objects are copied into the new array. The objects themselves are not copied. This is the usual rule for assignment of references, and the result is called a shallow copy.

original[0]slot holds a referenceStringBuilder AXone shared objectoriginal[1]slot holds a referenceStringBuilder Bone shared objectcopy[0]slot holds a referencecopy[1]slot holds a referencerefers torefers torefers torefers to
After copy[0] has been changed through the copy, do the original array and the copy still lead to the same object?
Code walkthrough
import java.util.Arrays;

public class ShallowDemo {
    public static void main(String[] args) {
        StringBuilder[] original = { new StringBuilder("A"), new StringBuilder("B") };
        StringBuilder[] copy = Arrays.copyOf(original, original.length);
        copy[0].append("X");
        System.out.println(original[0]);
        System.out.println(copy[0] == original[0]);
    }
}
  1. 1
    Line 4 creates an array of two StringBuilder references, each pointing to a new object.
  2. 2
    Line 5 copies the array with copyOf. The new array holds the same two references, not new copies of the objects.
  3. 3
    Line 6 calls append on the object reached through copy[0], changing it from A to AX.
  4. 4
    Line 7 prints original[0], which reaches the same object and therefore shows AX.
  5. 5
    Line 8 prints true because both array slots refer to the same object.
  • Each array slot holds a reference to a StringBuilder object
  • copyOf copies the references, so copy[0] and original[0] refer to the same StringBuilder
  • append changes the shared object, so the change is visible through both arrays
Output
AX
true

One Name, Many Overloads

The source makes a point that is easy to skim past: the methods in the Arrays class, copyOf included, come in multiple versions, and each version is written for a different array type. Arrays.copyOf is therefore not one method that handles every kind of array in exactly one way. It is a family of methods that share a name, with each member written for one kind of array.

When you call the method, Java selects the version that matches the array you pass in. Passing an int array selects the int version, and passing a String array selects the object version. You do not need to remember a separate name for each array type. You need to make sure the array you pass in is the type you intend to copy.

Best practice

Store the result of every copying call in a variable of the matching array type, such as int[] or String[]. The declared type then makes it clear which version of the method you meant, and it keeps the copy available for later use.

Mistakes When Copying Arrays

  • Common mistake

    Calling Arrays.copyOf without assigning its result

    What it looks like
    Arrays.copyOf(scores, 6); followed by a print of scores
    Why it fails

    copyOf is a function. It does not change its input, so scores is unchanged and the new array is thrown away.

    Do this instead
    int[] bigger = Arrays.copyOf(scores, 6); and then use bigger.
  • Common mistake

    Expecting clone() to resize an array

    What it looks like
    int[] bigger = scores.clone(); when a larger array is needed
    Why it fails

    clone() has no length argument, so it produces a copy of the same size only.

    Do this instead

    Use Arrays.copyOf(scores, newLength) when the size must change.

  • Common mistake

    Assuming an object array copy is independent of the original

    What it looks like

    Changing copy[0] through append and expecting original[0] to stay the same

    Why it fails

    A copy of an object array holds the same object references, so changes to the objects are shared.

    Do this instead

    Expect shared objects after copying, and create new objects where independent contents are required.

  • Common mistake

    Forgetting the default values in the extra positions

    What it looks like

    Expecting copyOf(numbers, 5) to contain only the original values

    Why it fails

    A longer result fills the extra positions with default values: zero for numeric arrays and null for object arrays.

    Do this instead

    Expect 0 or null in the added positions, and set real values there before relying on them.

Practice Predicting a Copy

MEDIUM

Given int[] nums = {4, 8, 15}; int[] bigger = Arrays.copyOf(nums, 6); bigger[1] = 99; predict the contents of bigger and the value of nums[1] after these lines run. Explain your answer by pointing to where the copy stopped sharing with the original.

Hints
  • Ask first whether copyOf makes a new array or changes nums.
  • Look at which original positions are copied and what the extra positions contain.
  • An int array stores numbers directly, so assigning to bigger[1] does not affect nums.

Key Takeaways

  • Java's standard array-processing methods are static methods in the Arrays class, in the package java.util, and are called with the class name, the method name, and the arguments.
  • Arrays.copyOf(array, length) returns a new array of the requested length, copies items by position, fills extra positions with default values, and does not change its input.
  • Doubling or halving the length with copyOf resizes a partly used array, while clone() makes only a same-size copy and takes no length argument.
  • Copying an array of objects produces a shallow copy, so the new array shares the same object instances with the original.
  • The Arrays class provides one version of its methods for each array type, and Java selects the version that matches the array passed in.