How to Sort an Array in Descending Order in Java
Sorting in descending order feels like it should be as simple as sorting ascending—but Java's built-in Arrays.sort() method for primitive arrays has a surprising limitation: it doesn't support a Comparator at all, meaning the seemingly obvious Arrays.sort(arr, Collections.reverseOrder()) simply won't compile for an int[]. This guide explains why that happens and walks through every practical workaround.
Problem Statement
Given an unsorted array like {5, 2, 9, 1, 5, 6}, the goal is to rearrange its elements in non-increasing order:
{9, 6, 5, 5, 2, 1}
The Primitive Array Challenge
Here's the trap many developers hit:
int[] numbers = {5, 2, 9, 1, 5, 6};
Arrays.sort(numbers, Collections.reverseOrder()); // Compile error!
This fails to compile because Arrays.sort(int[], Comparator) doesn't exist as an overload. Java's comparator-based sort methods only work with object arrays (Integer[], String[], etc.), not primitive arrays (int[], double[], etc.). This is a well-known Java quirk that catches many developers, including experienced ones working with arrays for the first time in a while.
Method 1: Manual Bubble Sort (Descending)
public class BubbleSortDescending {
public static void main(String[] args) {
int[] numbers = {5, 2, 9, 1, 5, 6};
for (int i = 0; i < numbers.length - 1; i++) {
for (int j = 0; j < numbers.length - 1 - i; j++) {
if (numbers[j] < numbers[j + 1]) {
int temp = numbers[j];
numbers[j] = numbers[j + 1];
numbers[j + 1] = temp;
}
}
}
System.out.println(java.util.Arrays.toString(numbers));
}
}
This is identical to ascending bubble sort, but the comparison is flipped: numbers[j] < numbers[j + 1] triggers a swap, pushing larger values toward the front instead of the back.
Method 2: Sort Ascending, Then Reverse (Simplest for Primitives)
import java.util.Arrays;
int[] numbers = {5, 2, 9, 1, 5, 6};
Arrays.sort(numbers); // ascending: [1, 2, 5, 5, 6, 9]
for (int i = 0; i < numbers.length / 2; i++) {
int temp = numbers[i];
numbers[i] = numbers[numbers.length - 1 - i];
numbers[numbers.length - 1 - i] = temp;
}
// numbers is now [9, 6, 5, 5, 2, 1]
This two-step approach—sort ascending with the built-in method, then reverse manually—is generally the simplest and most efficient practical solution for primitive arrays.
Method 3: Boxed Array With Collections.reverseOrder()
If you're working with Integer[] instead of int[], the comparator-based approach works directly:
import java.util.Arrays;
import java.util.Collections;
Integer[] numbers = {5, 2, 9, 1, 5, 6};
Arrays.sort(numbers, Collections.reverseOrder());
// numbers is now [9, 6, 5, 5, 2, 1]
This works because Integer[] is an object array, and Arrays.sort(T[], Comparator<? super T>) is a valid overload for object types.
Method 4: Java Streams
import java.util.Arrays;
import java.util.Collections;
int[] descending = Arrays.stream(numbers)
.boxed()
.sorted(Collections.reverseOrder())
.mapToInt(Integer::intValue)
.toArray();
This boxes each int into an Integer using .boxed(), sorts using the reverse comparator, then unboxes everything back into a primitive array.
Step-by-Step Explanation
Why Primitives Can't Use Comparator
Comparator<T> is a generic interface, and Java generics don't work with primitive types directly (you can't write Comparator<int>). This is why only boxed types like Integer can use comparator-based sorting.
The Reverse-After-Sort Trick
Sorting ascending first guarantees a known, correct order. Reversing that order in a simple swap loop (numbers.length / 2 iterations, swapping symmetric pairs from both ends toward the middle) is both simple and efficient.
The Streams Approach
The streams solution explicitly boxes primitive values into objects so that Collections.reverseOrder() can be applied. After sorting, the values are unboxed back into a primitive array for efficient storage.
Internal Working (Memory View)
For Method 2, after Arrays.sort(numbers) produces:
[1, 2, 5, 5, 6, 9]
The reversal loop performs these swaps:
i = 0: swap index0and5→[9, 2, 5, 5, 6, 1]i = 1: swap index1and4→[9, 6, 5, 5, 2, 1]i = 2: swap index2and3→[9, 6, 5, 5, 2, 1]
The loop only runs length / 2 times because each swap correctly positions two elements simultaneously.
Real-Life Analogy
Imagine arranging trophies on a shelf from smallest to largest, then simply walking to the other end of the shelf and reading them in reverse order to get largest-to-smallest. You don't need to rearrange everything again—you simply reverse the order.
Best Practices
- For primitive arrays, sort ascending with
Arrays.sort()and then reverse manually because it's simpler and more efficient than boxing and unboxing. - For object arrays (
Integer[],String[], or custom objects), useArrays.sort(array, Collections.reverseOrder())directly. - Avoid unnecessary boxing and unboxing in performance-critical code. Use the streams approach only when you're already working within a stream pipeline.
- Always verify whether you're working with a primitive (
int[]) or object (Integer[]) array before choosing a sorting strategy.
Common Mistakes
- Trying
Arrays.sort(intArray, Comparator...)directly, which fails because no such overload exists for primitive arrays. - Forgetting to unbox after using streams, resulting in an
Integer[]when anint[]is expected. - Reversing the array inefficiently by looping through the entire array instead of only half of it.
- Confusing
Comparator.reverseOrder()withCollections.reverseOrder(). Both produce reverse-order comparators but belong to different utility classes.
Expert Tips
Comparator.reverseOrder()andCollections.reverseOrder()are functionally equivalent for natural ordering. Choose whichever reads more naturally in your code.- For sorting custom objects in descending order by a specific field, use:
Arrays.sort(employees,
Comparator.comparing(Employee::getSalary).reversed());
- If descending sorting is frequently needed in your application, consider creating a reusable utility method that performs the "sort ascending then reverse" logic.
Comparison Table
| Method | Works With Primitives? | Time Complexity | Simplicity |
|---|---|---|---|
| Manual Bubble Sort (Descending) | ✅ Yes | O(n²) | Medium |
| Sort Ascending + Manual Reverse | ✅ Yes | O(n log n) | High (Recommended) |
Collections.reverseOrder() (Boxed) |
⚠️ Only with Integer[] |
O(n log n) | High |
| Streams (Box → Sort → Unbox) | ✅ Yes (via boxing) | O(n log n) | Medium |
Frequently Asked Questions
Why can't I use Arrays.sort() with a Comparator on an int[]?
Because Comparator is generic, and Java generics don't support primitive types directly. Only object arrays such as Integer[] support comparator-based sorting.
What's the simplest way to sort a primitive int array in descending order?
Sort it in ascending order using Arrays.sort(), then reverse it manually using a simple swap loop.
How do I sort an Integer[] array in descending order?
Use:
Arrays.sort(integerArray, Collections.reverseOrder());
Is bubble sort a good choice for descending sorting in production?
No. Like ascending bubble sort, it has O(n²) time complexity and is mainly useful for learning or interviews.
What's the difference between Comparator.reverseOrder() and Collections.reverseOrder()?
They are functionally equivalent for natural ordering but belong to different utility classes.
Can streams sort a primitive array in descending order directly?
No. IntStream doesn't support comparator-based sorting. You must first convert primitives to Integer objects using .boxed(), sort them, and then convert them back to int.
How do I sort custom objects in descending order by a specific field?
Use:
Arrays.sort(
objectArray,
Comparator.comparing(YourClass::getField).reversed()
);
Does reversing a sorted ascending array always produce a correctly sorted descending array?
Yes. Reversing a correctly ascending-sorted array always produces a correctly descending-sorted array.