Back to Blog
Java

Java Arrays.binarySearch: Usage and Common Pitfalls

How to use Arrays.binarySearch in Java, understand its return value, handle edge cases, and compare it with alternatives.

JavaBinary SearchArraysComparatorPerformance
Illustration of Java Arrays binary search showing a sorted array and a highlighted element.

Arrays.binarySearch performs a binary search on a sorted array and returns the index of the target value when it is present. When the value is absent, it returns a negative number that encodes the insertion point instead of a bare -1. The examples below assume java.util.Arrays is imported.

The Contract of Arrays.binarySearch

Arrays.binarySearch is a static method that performs a binary search on an array. It is overloaded for every ordered primitive type (byte, char, double, float, int, long, short) and for object arrays.

int index = Arrays.binarySearch(intArray, 42);

The return value follows a strict contract:

  • If the key is found, the method returns the index of the key.
  • If the key is not found, it returns (-(insertionPoint) - 1), where insertionPoint is the index at which the key would be inserted to maintain sorted order.

The array must already be sorted according to the ordering used by the search. For primitive arrays, that means ascending numeric order. For object arrays, the ordering can come from the elements' natural ordering or from the Comparator passed to the method.

Basic Examples with Primitive Arrays

Consider a sorted array of integers:

int[] numbers = {2, 5, 8, 12, 16}; int index = Arrays.binarySearch(numbers, 8); // index == 2

If the key is missing:

int missingIndex = Arrays.binarySearch(numbers, 9); // missingIndex == -4 because insertionPoint is 3

The negative value follows the formula -(insertionPoint) - 1. To recover the insertion point, use Math.abs(missingIndex) - 1.

Searching Object Arrays with a Comparator

For custom objects, you must either implement Comparable or pass a Comparator to the overloaded method:

record Person(String name, int age) {} Person[] people = { new Person("Alice", 30), new Person("Bob", 25), new Person("Carol", 35) }; // Sort by age before searching Arrays.sort(people, Comparator.comparingInt(Person::age)); int index = Arrays.binarySearch(people, new Person("Bob", 25), Comparator.comparingInt(Person::age));

The comparator used for searching must impose the same ordering as the one used for sorting. If the two comparators disagree, the result is undefined.

Understanding the Return Value and Insertion Point

The negative return value is often misunderstood. It is not simply -1 when the element is absent; it encodes the position where the element would fit. This is useful for implementing insertion logic without a separate linear scan.

For example, to insert a new element into a sorted array while preserving order:

int pos = Arrays.binarySearch(sortedArray, newValue); if (pos < 0) { int insertionPoint = -pos - 1; // Shift elements and insert at insertionPoint }

This pattern is common in algorithms that maintain sorted collections manually.

Edge Cases and Common Pitfalls

Unsorted Array

The most frequent mistake is calling binarySearch on an array that has not been sorted. The method assumes the array is sorted and does not check. The result is unpredictable and can lead to subtle bugs.

Duplicate Elements

If the array contains duplicates, binarySearch does not guarantee which duplicate index is returned. The contract only says that if the key is present, the returned index is a valid index of the key. This can be problematic if you need the first or last occurrence. For that, scan linearly around the found index or use a different approach.

Null Elements

For object arrays, if the array contains null and the comparator does not handle it, a NullPointerException may be thrown. If you rely on natural ordering, null is not comparable and will also cause a NullPointerException. Ensure your comparator handles null if your array may contain nulls.

Empty Array

An empty array always returns a negative value based on insertion point 0: -1. This follows directly from the formula.

Performance Characteristics

Binary search runs in O(log n) time, which is significantly faster than linear search for large arrays. However, the benefit only materializes if the array is already sorted. Sorting itself is typically O(n log n), so if you need to search only once, a linear scan may be simpler and faster for small arrays. For repeated searches on a static dataset, sorting once and then using binary search is the right approach.

In the standard Java implementation, the search is iterative and does not allocate arrays or collections, so it adds little overhead beyond the comparisons themselves.

Alternatives and Comparison

Arrays.binarySearch works on arrays. For List implementations, Collections.binarySearch provides similar functionality. The two methods have the same contract, but Collections.binarySearch works on any List; to get O(log n) time, the list must support random access, like ArrayList. For LinkedList, binary search may degrade to O(n) because of the lack of random access.

MethodInput TypeRandom Access RequiredTypical Use Case
Arrays.binarySearchArrayYesFixed-size sorted data
Collections.binarySearchListYes (for O(log n))Dynamic but sorted collections
Manual binary searchArray or random-access collectionYesCustom implementations

Choosing between these depends on your data structure. If you already have an array, use Arrays.binarySearch. If you have a List, use Collections.binarySearch. If you have a custom collection with random access, implement the algorithm directly.

Arrays.binarySearch in Java: Usage and Common Pitfalls | RYUSLOG DEV