JB Header

Java Arrays Class: sort, binarySearch, fill, copyOf

Introduction Sorting, searching, copying and comparing arrays are needed in almost every program, and you do not have to write them yourself. The java.util.Arrays class provides tested, fast methods for all of them. This tutorial explains the most useful methods of the Arrays class with examples. We will start with printing arrays with toString(). We will then sort arrays with sort(), and search sorted arrays with binarySearch(). Next we will fill arrays with fill() and copy them with copyOf() and copyOfRange(). Lastly, we will compare arrays with equals() and compare(), and turn arrays into lists and streams.

(Note - This tutorial builds on Java Arrays: Declare, Create and InitializeClick to read tutorial: Java Arrays Tutorial: Declare, Create and Initialize. All methods of Arrays are static, so they are called on the class: Arrays.sort(numbers).) Printing arrays - toString() and deepToString() Printing an array directly prints its type and hash code, such as [I@4e50df2e. Arrays.toString() returns its elements instead, and Arrays.deepToString() does the same for nested arrays.
Printing arrays
//PrintArrays.java
import java.util.Arrays;

public class PrintArrays {
  public static void main(String[] args) {
    int[] numbers = {5, 3, 8};
    int[][] grid = {{1, 2}, {3, 4}};
    System.out.println("toString     : " + Arrays.toString(numbers));
    System.out.println("deepToString : " + Arrays.deepToString(grid));
    System.out.println("toString(2D) : " + Arrays.toString(grid).replaceAll("@[0-9a-f]+", "@..."));
  }
}
 OUTPUT of the above code
toString     : [5, 3, 8]
deepToString : [[1, 2], [3, 4]]
toString(2D) : [[I@..., [I@...]
toString() on a 2D array only shows the references of the rows ([I@... means "an int array at some address"), which is why nested arrays need deepToString(). Sorting - sort() Arrays.sort() sorts an array in place - it rearranges the original array, and returns nothing.
  • Numbers are sorted in ascending order, and strings in natural (dictionary) order, where all capital letters come before lower-case ones.
  • sort(array, from, to) sorts only the part from index from up to, but not including, to.
  • For object arrays, a Comparator gives any order you need - reverse, by length, case-insensitive and so on.
Sorting arrays
//SortDemo.java
import java.util.Arrays;
import java.util.Comparator;

public class SortDemo {
  public static void main(String[] args) {
    int[] scores = {72, 95, 64, 88, 79};
    Arrays.sort(scores);
    System.out.println("Sorted scores  : " + Arrays.toString(scores));

    String[] names = {"harry", "Tom", "ethan", "Nancy"};
    Arrays.sort(names);
    System.out.println("Natural order  : " + Arrays.toString(names));

    Arrays.sort(names, String.CASE_INSENSITIVE_ORDER);
    System.out.println("Ignoring case  : " + Arrays.toString(names));

    Arrays.sort(names, Comparator.comparing(String::length).thenComparing(Comparator.reverseOrder()));
    System.out.println("By length      : " + Arrays.toString(names));

    Integer[] boxed = {3, 1, 2};
    Arrays.sort(boxed, Comparator.reverseOrder());
    System.out.println("Descending     : " + Arrays.toString(boxed));

    int[] partial = {9, 8, 7, 6, 5, 4};
    Arrays.sort(partial, 1, 4);
    System.out.println("Sort index 1-3 : " + Arrays.toString(partial));
  }
}
 OUTPUT of the above code
Sorted scores  : [64, 72, 79, 88, 95]
Natural order  : [Nancy, Tom, ethan, harry]
Ignoring case  : [ethan, harry, Nancy, Tom]
By length      : [Tom, harry, ethan, Nancy]
Descending     : [3, 2, 1]
Sort index 1-3 : [9, 6, 7, 8, 5, 4]
Explanation of the code
  • In natural order, "Nancy" and "Tom" come before "ethan" and "harry", because upper-case letters have smaller Unicode values. String.CASE_INSENSITIVE_ORDER fixes that.
  • Comparators can be combined: sort by length, and break ties by reverse alphabetical order. Comparators are covered in depth in The Complete Java 8 Comparator TutorialClick to read The Complete Java 8 Comparator Tutorial.
  • A primitive array such as int[] cannot be sorted with a comparator. To sort numbers in descending order, use an Integer[], as here, or sort ascending and read the array backwards.
  • sort(partial, 1, 4) sorted only indexes 1, 2 and 3, leaving the rest untouched.
Searching - binarySearch() Arrays.binarySearch() finds a value in a sorted array very quickly. Instead of checking every element, it repeatedly halves the part of the array that could contain the value - so even a million elements need only about 20 comparisons.
  • If the value is found, it returns the value's index.
  • If not, it returns a negative number: -(insertion point) - 1, where the insertion point is the index at which the value would be inserted to keep the array sorted.
  • The array must be sorted first. On an unsorted array, the result is meaningless.
Searching a sorted array with binarySearch()
//SearchDemo.java
import java.util.Arrays;

public class SearchDemo {
  public static void main(String[] args) {
    int[] ids = {104, 215, 330, 487, 512, 690};
    System.out.println("Index of 487 : " + Arrays.binarySearch(ids, 487));
    System.out.println("Index of 104 : " + Arrays.binarySearch(ids, 104));

    int result = Arrays.binarySearch(ids, 400);
    System.out.println("Search for 400 returns " + result);
    if (result < 0) {
      int insertionPoint = -result - 1;
      System.out.println("400 is not there; it belongs at index " + insertionPoint);
    }

    int[] unsorted = {512, 104, 690, 215};
    System.out.println("On an unsorted array: " + Arrays.binarySearch(unsorted, 215));
  }
}
 OUTPUT of the above code
Index of 487 : 3
Index of 104 : 0
Search for 400 returns -4
400 is not there; it belongs at index 3
On an unsorted array: -3
On the unsorted array, binarySearch() returned a negative number - "not found" - for 215, although it is in the array. Sort first - or, for a one-off search in a small unsorted array, simply loop through it. Filling and copying - fill(), copyOf() and copyOfRange()
  • fill(array, value) sets every element - or, with a range, some of them - to one value.
  • copyOf(array, newLength) returns a new array of the given length. A shorter length cuts the copy; a longer one pads it with default values. This is how you "grow" an array.
  • copyOfRange(array, from, to) returns a new array with the elements from index from up to, but not including, to.
  • setAll(array, function) sets each element from its index, using a lambda.
Filling and copying arrays
//FillCopyDemo.java
import java.util.Arrays;

public class FillCopyDemo {
  public static void main(String[] args) {
    int[] seats = new int[6];
    Arrays.fill(seats, -1);
    Arrays.fill(seats, 2, 4, 0);
    System.out.println("fill        : " + Arrays.toString(seats));

    int[] original = {10, 20, 30, 40, 50};
    int[] shorter = Arrays.copyOf(original, 3);
    int[] longer = Arrays.copyOf(original, 7);
    int[] middle = Arrays.copyOfRange(original, 1, 4);
    System.out.println("copyOf 3    : " + Arrays.toString(shorter));
    System.out.println("copyOf 7    : " + Arrays.toString(longer));
    System.out.println("copyOfRange : " + Arrays.toString(middle));

    longer[0] = 999;
    System.out.println("original    : " + Arrays.toString(original) + " (unchanged)");

    int[] squares = new int[6];
    Arrays.setAll(squares, i -> i * i);
    System.out.println("setAll      : " + Arrays.toString(squares));
  }
}
 OUTPUT of the above code
fill        : [-1, -1, 0, 0, -1, -1]
copyOf 3    : [10, 20, 30]
copyOf 7    : [10, 20, 30, 40, 50, 0, 0]
copyOfRange : [20, 30, 40]
original    : [10, 20, 30, 40, 50] (unchanged)
setAll      : [0, 1, 4, 9, 16, 25]
The copies are new arrays, so changing longer did not affect original. System.arraycopy() is a lower-level alternative which copies elements into an existing array.
Comparing arrays - equals(), deepEquals() and compare() == only tells you whether two variables refer to the same array object. To compare contents -
  • Arrays.equals(a, b) - true if both arrays have the same length and equal elements in the same order.
  • Arrays.deepEquals(a, b) - the same for nested arrays.
  • Arrays.compare(a, b) - compares arrays element by element, like words in a dictionary, and returns a negative number, zero or a positive number.
  • Arrays.mismatch(a, b) - the index of the first difference, or -1 if there is none.
Comparing arrays
//CompareDemo.java
import java.util.Arrays;

public class CompareDemo {
  public static void main(String[] args) {
    int[] a = {1, 2, 3};
    int[] b = {1, 2, 3};
    int[] c = {1, 2, 4};
    System.out.println("a == b          : " + (a == b));
    System.out.println("equals(a, b)    : " + Arrays.equals(a, b));
    System.out.println("equals(a, c)    : " + Arrays.equals(a, c));
    System.out.println("compare(a, c)   : " + Arrays.compare(a, c));
    System.out.println("mismatch(a, c)  : " + Arrays.mismatch(a, c));

    int[][] x = {{1, 2}, {3}};
    int[][] y = {{1, 2}, {3}};
    System.out.println("equals(x, y)    : " + Arrays.equals(x, y));
    System.out.println("deepEquals(x, y): " + Arrays.deepEquals(x, y));
  }
}
 OUTPUT of the above code
a == b          : false
equals(a, b)    : true
equals(a, c)    : false
compare(a, c)   : -1
mismatch(a, c)  : 2
equals(x, y)    : false
deepEquals(x, y): true
For the 2D arrays, equals() compared the row references, which differ, so only deepEquals() gave the right answer. Arrays to lists and streams - asList() and stream() Arrays.asList() views an object array as a fixed-size List, and Arrays.stream() creates a stream for calculations such as sum and average.
Turning arrays into lists and streams
//ListStreamDemo.java
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class ListStreamDemo {
  public static void main(String[] args) {
    String[] names = {"Tom", "Harry", "Ethan"};
    List<String> fixed = Arrays.asList(names);
    System.out.println("asList   : " + fixed + ", contains Harry: " + fixed.contains("Harry"));
    List<String> growable = new ArrayList<>(Arrays.asList(names));
    growable.add("Nancy");
    System.out.println("growable : " + growable);

    int[] scores = {72, 95, 64, 88, 79};
    System.out.println("sum      : " + Arrays.stream(scores).sum());
    System.out.println("max      : " + Arrays.stream(scores).max().getAsInt());
    System.out.println("average  : " + Arrays.stream(scores).average().getAsDouble());

    fixed.add("Nancy");
  }
}
 OUTPUT of the above code
asList   : [Tom, Harry, Ethan], contains Harry: true
growable : [Tom, Harry, Ethan, Nancy]
sum      : 398
max      : 95
average  : 79.6
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 ListStreamDemo.main(ListStreamDemo.java:20)
Explanation of the code
  • The list from asList() is backed by the array, and its size is fixed - so fixed.add() threw an UnsupportedOperationException. Copy it into a new ArrayList<>(...) for a list which can grow.
  • Arrays.stream() on an int[] gives an IntStream, with ready-made sum(), max() and average(). See the Java 8 Streams API TutorialClick to read tutorial on the Streams API.
Summary In this tutorial we first printed arrays with toString() and deepToString(). We then sorted arrays with sort() - whole or partial, in natural order or with a comparator - and searched sorted arrays with binarySearch(), including its negative "not found" result. Next we filled arrays with fill() and setAll(), and copied them with copyOf() and copyOfRange(). We then compared arrays with equals(), deepEquals(), compare() and mismatch(). Lastly, we turned arrays into lists with asList() and streams with stream(). In the next tutorial, we will put arrays to work in common array programsClick to read tutorial: Common Java Array Programs with Examples.