Sorting arrays is a fundamental operation in software development. In Java, you can use the Comparator interface to define custom sorting logic for arrays of objects. This gives you full control over ascending or descending order based on specific attributes.
This updated guide on javatechig.com shows how to sort arrays using Comparator, including object sorting, lambda syntax, and best practices aligned with modern Java standards.
Why Use Comparator for Sorting
The Comparator interface allows you to:
- Sort by custom criteria
- Switch between ascending/descending easily
- Sort complex objects (not just primitives)
- Maintain reusable comparison logic
Unlike natural ordering (Comparable), Comparator gives external sorting rules without modifying the class.
Sorting Primitive Arrays
Ascending Order (Wrapper Arrays)
Java’s Arrays.sort() can sort primitives directly:
int[] numbers = {5, 1, 9, 3, 7};
Arrays.sort(numbers); // ascending
For descending on primitives, convert to wrapper type:
Integer[] nums = {5, 1, 9, 3, 7};
Arrays.sort(nums, Collections.reverseOrder());
Sorting Object Arrays with Comparator
Assume you have an array of custom objects:
class Person {
String name;
int age;
// Constructor, getters
}
Sort Ascending by Age
Comparator<Person> byAgeAsc = Comparator.comparingInt(Person::getAge);
Arrays.sort(personArray, byAgeAsc);
This sorts the array by increasing age.
Sort Descending by Age
Comparator<Person> byAgeDesc = Comparator.comparingInt(Person::getAge).reversed();
Arrays.sort(personArray, byAgeDesc);
You can chain comparators as needed.
Sorting by Multiple Attributes
To sort first by age, then name:
Comparator<Person> composite = Comparator
.comparingInt(Person::getAge)
.thenComparing(Person::getName);
Arrays.sort(personArray, composite);
This ensures deterministic ordering with multiple fields.
Lambda‑Based Sorting
Ascending by Name
Arrays.sort(personArray, (p1, p2) -> p1.getName().compareTo(p2.getName()));
Descending by Name
Arrays.sort(personArray, (p1, p2) -> p2.getName().compareTo(p1.getName()));
The lambda approach is concise and readable.
Sorting with List instead of Array
When working with lists:
List<Person> list = Arrays.asList(personArray);
list.sort(Comparator.comparing(Person::getAge));
Or for descending:
list.sort(Comparator.comparing(Person::getAge).reversed());
Lists offer more flexibility than arrays for dynamic-sized data.
Using Streams for Sorting
Java Streams offer a functional approach:
Ascending
Person[] sorted = Arrays.stream(personArray)
.sorted(Comparator.comparing(Person::getAge))
.toArray(Person[]::new);
Descending
Person[] sortedDesc = Arrays.stream(personArray)
.sorted(Comparator.comparing(Person::getAge).reversed())
.toArray(Person[]::new);
Streams allow chaining additional operations like filtering.
Common Mistakes & Fixes
Using == for Comparison
For object attributes, always use comparison methods (compareTo), not ==.
Not Handling Nulls
When sorting, null elements can cause exceptions.
Fix with null‑safe comparator:
Comparator<Person> safeSort = Comparator.nullsLast(
Comparator.comparing(Person::getAge));
This places null elements after non‑null.
Performance Considerations
Arrays.sort()uses dual‑pivot quicksort for primitives and TimSort for objects- Sorting large arrays repeatedly is expensive — avoid redundant sorts
- For frequent updates, consider data structures like
TreeSet
Best Practices (2026 Updated)
- Prefer Comparator.comparing() with method references
- Use reversed() cleanly for descending order
- Leverage thenComparing() for multi‑level sort
- Use List.sort() and Streams for modern codebases
- Always handle nulls explicitly in real‑world data
Example Summary
| Use Case | Method |
|---|---|
| Ascending primitives | Arrays.sort() |
| Descending primitives | Collections.reverseOrder() |
| Object sort | Comparator.comparing() |
| Multi‑attribute | thenComparing() |
| Streams | stream().sorted() |


