Java Advanced Sorting
Custom sorting with Comparator and advanced techniques
🔄 What is Advanced Sorting?
Advanced sorting involves custom comparison logic using Comparator interface, lambda expressions, and method references. It enables complex sorting scenarios beyond natural ordering.
// Simple custom sorting
List<String> names = Arrays.asList("John", "Alice", "Bob");
names.sort((a, b) -> a.length() - b.length()); // Sort by length
System.out.println(names); // [Bob, John, Alice]
Output:
[Bob, John, Alice]
Sorted by string length instead of alphabetical order
Sorting Techniques
Comparator
Custom comparison logic
Comparator.comparing(Person::getName)
Method Reference
Concise comparator syntax
String::compareToIgnoreCase
Multiple Criteria
Chain multiple comparisons
comparing(Person::getAge)
.thenComparing(Person::getName)
Reverse Order
Descending sort
Comparator.reverseOrder()
🔹 Comparator Interface
Using Comparator for custom sorting logic:
import java.util.*;
import java.util.stream.Collectors;
class Person {
private String name;
private int age;
private double salary;
public Person(String name, int age, double salary) {
this.name = name;
this.age = age;
this.salary = salary;
}
// Getters
public String getName() { return name; }
public int getAge() { return age; }
public double getSalary() { return salary; }
@Override
public String toString() {
return String.format("%s (age: %d, salary: %.0f)", name, age, salary);
}
}
public class ComparatorExample {
public static void main(String[] args) {
List<Person> people = Arrays.asList(
new Person("Alice", 30, 50000),
new Person("Bob", 25, 60000),
new Person("Charlie", 35, 45000),
new Person("David", 25, 55000)
);
// Sort by age (ascending)
List<Person> byAge = people.stream()
.sorted(Comparator.comparing(Person::getAge))
.collect(Collectors.toList());
System.out.println("By Age: " + byAge);
// Sort by salary (descending)
List<Person> bySalary = people.stream()
.sorted(Comparator.comparing(Person::getSalary).reversed())
.collect(Collectors.toList());
System.out.println("By Salary (desc): " + bySalary);
// Sort by name length
List<Person> byNameLength = people.stream()
.sorted(Comparator.comparing(p -> p.getName().length()))
.collect(Collectors.toList());
System.out.println("By Name Length: " + byNameLength);
}
}
Output:
By Age: [Bob (age: 25, salary: 60000), David (age: 25, salary: 55000), Alice (age: 30, salary: 50000), Charlie (age: 35, salary: 45000)]
By Salary (desc): [Bob (age: 25, salary: 60000), David (age: 25, salary: 55000), Alice (age: 30, salary: 50000), Charlie (age: 35, salary: 45000)]
By Name Length: [Bob, Alice, David, Charlie]
🔹 Multiple Criteria Sorting
Sorting by multiple fields using thenComparing:
import java.util.*;
public class MultiCriteriaSorting {
public static void main(String[] args) {
List<Person> employees = Arrays.asList(
new Person("Alice", 30, 50000),
new Person("Bob", 25, 60000),
new Person("Charlie", 25, 45000),
new Person("David", 30, 55000),
new Person("Eve", 25, 60000)
);
System.out.println("Original list:");
employees.forEach(System.out::println);
// Sort by age first, then by salary (descending), then by name
List<Person> sorted = employees.stream()
.sorted(Comparator.comparing(Person::getAge)
.thenComparing(Person::getSalary, Comparator.reverseOrder())
.thenComparing(Person::getName))
.collect(Collectors.toList());
System.out.println("\nSorted by age, then salary (desc), then name:");
sorted.forEach(System.out::println);
// Custom comparator with lambda
employees.sort((p1, p2) -> {
int ageCompare = Integer.compare(p1.getAge(), p2.getAge());
if (ageCompare != 0) return ageCompare;
int salaryCompare = Double.compare(p2.getSalary(), p1.getSalary()); // Reverse
if (salaryCompare != 0) return salaryCompare;
return p1.getName().compareTo(p2.getName());
});
System.out.println("\nUsing custom lambda comparator:");
employees.forEach(System.out::println);
}
}
Output:
Original list: Alice (30, 50000), Bob (25, 60000), Charlie (25, 45000), David (30, 55000), Eve (25, 60000)
Sorted: Bob (25, 60000), Eve (25, 60000), Charlie (25, 45000), David (30, 55000), Alice (30, 50000)
🔹 Advanced Sorting Techniques
Specialized sorting scenarios and optimizations:
import java.util.*;
import java.util.function.Function;
public class AdvancedSortingTechniques {
// Custom sorting with null handling
public static void nullSafeSorting() {
List<String> words = Arrays.asList("apple", null, "banana", "cherry", null, "date");
// Nulls first, then alphabetical
words.sort(Comparator.nullsFirst(String::compareTo));
System.out.println("Nulls first: " + words);
// Nulls last, then alphabetical
words.sort(Comparator.nullsLast(String::compareTo));
System.out.println("Nulls last: " + words);
}
// Case-insensitive sorting
public static void caseInsensitiveSorting() {
List<String> names = Arrays.asList("alice", "BOB", "Charlie", "david");
names.sort(String.CASE_INSENSITIVE_ORDER);
System.out.println("Case insensitive: " + names);
// Using method reference
names.sort(String::compareToIgnoreCase);
System.out.println("Method reference: " + names);
}
// Sorting with custom key extraction
public static void keyExtractionSorting() {
List<String> sentences = Arrays.asList(
"The quick brown fox",
"jumps over the lazy dog",
"Hello world",
"Java programming is fun"
);
// Sort by word count
sentences.sort(Comparator.comparing(s -> s.split(" ").length));
System.out.println("By word count: " + sentences);
// Sort by last word
sentences.sort(Comparator.comparing(s -> {
String[] words = s.split(" ");
return words[words.length - 1];
}));
System.out.println("By last word: " + sentences);
}
// Stable sorting demonstration
public static void stableSorting() {
List<Person> people = Arrays.asList(
new Person("Alice", 25, 50000),
new Person("Bob", 25, 60000),
new Person("Charlie", 30, 45000),
new Person("David", 25, 55000)
);
System.out.println("Original order:");
people.forEach(System.out::println);
// Stable sort by age (maintains relative order for equal elements)
people.sort(Comparator.comparing(Person::getAge));
System.out.println("Stable sort by age:");
people.forEach(System.out::println);
}
public static void main(String[] args) {
System.out.println("=== Null Safe Sorting ===");
nullSafeSorting();
System.out.println("\n=== Case Insensitive Sorting ===");
caseInsensitiveSorting();
System.out.println("\n=== Key Extraction Sorting ===");
keyExtractionSorting();
System.out.println("\n=== Stable Sorting ===");
stableSorting();
}
}
Output:
Nulls first: [null, null, apple, banana, cherry, date]
Case insensitive: [alice, BOB, Charlie, david]
By word count: [Hello world, The quick brown fox, Java programming is fun, jumps over the lazy dog]
Stable sort maintains original order for equal age values