Comparator definition is crucial for sorting and ordering objects in Java, and compare.edu.vn offers a deep dive into its functionalities. This guide explores comparators, their importance, and how they can be used effectively to enhance data manipulation in various applications, providing you with the tools to make informed decisions. Explore the benefits of comparator implementation, comparator interface, and comparator example.
1. Understanding Comparators
A comparator is an interface in Java used to define a custom ordering for objects of a class. It is part of the Java Collections Framework and plays a crucial role in sorting and ordering elements in collections. This section explores the fundamental aspects of comparators, including their definition, purpose, and how they differ from comparable interfaces.
1.1. Definition of a Comparator
In Java, a comparator is an interface (java.util.Comparator) that provides a way to define a total ordering on some collection of objects. Unlike the Comparable
interface, which requires the class itself to implement the comparison logic, a comparator is a separate class that can be created to compare objects of another class.
The comparator interface consists of a single method:
int compare(Object obj1, Object obj2);
This method compares two objects and returns an integer value indicating their relative order:
- Negative value:
obj1
is less thanobj2
. - Zero:
obj1
is equal toobj2
. - Positive value:
obj1
is greater thanobj2
.
1.2. Purpose of Using Comparators
The primary purpose of using comparators is to provide flexibility in sorting and ordering objects. Comparators are particularly useful in scenarios where:
- The class does not implement the
Comparable
interface. - The default ordering provided by the
Comparable
interface is not suitable. - Multiple ordering criteria are required for the same class.
- The sorting logic needs to be customized based on specific requirements.
Comparators allow developers to define different sorting strategies without modifying the original class. This promotes code reusability and maintainability.
1.3. Comparator vs. Comparable: Key Differences
Both Comparator
and Comparable
are used for sorting and ordering objects in Java, but they have distinct differences:
Feature | Comparator | Comparable |
---|---|---|
Interface | java.util.Comparator |
java.lang.Comparable |
Implementation | Separate class | Implemented by the class itself |
Method | int compare(Object obj1, Object obj2) |
int compareTo(Object obj) |
Modification | Does not require modification of the original class | Requires modification of the original class |
Flexibility | Allows multiple sorting strategies for the same class | Provides a single, natural ordering for the class |
Use Case | External sorting logic or multiple sorting criteria needed | Default ordering for the class is sufficient or the class needs a natural ordering |
Comparable
is suitable when the class has a natural ordering that is always the same. Comparator
is used when you need to define different ordering strategies or when the class does not implement Comparable
.
2. Creating a Comparator in Java
Creating a comparator involves implementing the java.util.Comparator
interface and providing the comparison logic in the compare()
method. This section guides you through the steps to create a comparator, providing code examples and best practices.
2.1. Implementing the Comparator Interface
To create a comparator, you need to implement the java.util.Comparator
interface. This involves creating a class that implements the interface and overrides the compare()
method.
Here’s a basic example of creating a comparator for a Student
class:
import java.util.Comparator;
public class Student {
private int id;
private String name;
private double gpa;
public Student(int id, String name, double gpa) {
this.id = id;
this.name = name;
this.gpa = gpa;
}
public int getId() {
return id;
}
public String getName() {
return name;
}
public double getGpa() {
return gpa;
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + ''' +
", gpa=" + gpa +
'}';
}
}
class SortByGPA implements Comparator<Student> {
@Override
public int compare(Student s1, Student s2) {
return Double.compare(s1.getGpa(), s2.getGpa());
}
}
In this example, the SortByGPA
class implements the Comparator<Student>
interface. The compare()
method compares two Student
objects based on their GPA.
2.2. Writing the compare()
Method
The compare()
method is the heart of the comparator. It defines the logic for comparing two objects and determining their relative order. The method should return:
- A negative integer if the first object is less than the second object.
- Zero if the first object is equal to the second object.
- A positive integer if the first object is greater than the second object.
Here are some common patterns for writing the compare()
method:
-
Comparing Numbers:
public int compare(Student s1, Student s2) { return Integer.compare(s1.getId(), s2.getId()); }
-
Comparing Strings:
public int compare(Student s1, Student s2) { return s1.getName().compareTo(s2.getName()); }
-
Comparing Multiple Fields:
public int compare(Student s1, Student s2) { int nameComparison = s1.getName().compareTo(s2.getName()); if (nameComparison != 0) { return nameComparison; } return Double.compare(s2.getGpa(), s2.getGpa()); }
2.3. Best Practices for Creating Comparators
-
Handle Null Values: Ensure your comparator handles null values gracefully to avoid
NullPointerException
.public int compare(Student s1, Student s2) { if (s1 == null && s2 == null) return 0; if (s1 == null) return -1; if (s2 == null) return 1; return Integer.compare(s1.getId(), s2.getId()); }
-
Consider Edge Cases: Test your comparator with various edge cases to ensure it behaves as expected.
-
Use Static Constants: If the comparator is stateless, define it as a static constant to avoid unnecessary object creation.
public static final Comparator<Student> SORT_BY_ID = (s1, s2) -> Integer.compare(s1.getId(), s2.getId());
-
Use Comparator Chaining: Combine multiple comparators to create complex sorting logic.
Comparator<Student> chainedComparator = Comparator.comparing(Student::getName) .thenComparing(Student::getGpa);
3. Using Comparators with Collections
Comparators are commonly used with collections in Java to sort and order elements. This section demonstrates how to use comparators with various collection types, including lists, sets, and maps.
3.1. Sorting Lists with Comparators
The Collections.sort()
method can be used to sort a list using a comparator. This method takes a list and a comparator as arguments.
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class ComparatorExample {
public static void main(String[] args) {
List<Student> students = new ArrayList<>();
students.add(new Student(101, "Alice", 3.8));
students.add(new Student(102, "Bob", 3.6));
students.add(new Student(103, "Charlie", 3.9));
System.out.println("Before sorting: " + students);
Collections.sort(students, new SortByGPA());
System.out.println("After sorting by GPA: " + students);
}
}
In this example, the Collections.sort()
method sorts the list of Student
objects based on their GPA, using the SortByGPA
comparator.
3.2. Using Comparators with Sorted Sets
Sorted sets, such as TreeSet
, maintain their elements in a sorted order. You can provide a comparator to the TreeSet
constructor to define the sorting order.
import java.util.Set;
import java.util.TreeSet;
public class ComparatorExample {
public static void main(String[] args) {
Set<Student> students = new TreeSet<>(new SortByGPA());
students.add(new Student(101, "Alice", 3.8));
students.add(new Student(102, "Bob", 3.6));
students.add(new Student(103, "Charlie", 3.9));
System.out.println("Sorted set by GPA: " + students);
}
}
In this example, the TreeSet
is created with the SortByGPA
comparator, ensuring that the Student
objects are stored in ascending order of GPA.
3.3. Using Comparators with Sorted Maps
Sorted maps, such as TreeMap
, maintain their entries in a sorted order based on the keys. You can provide a comparator to the TreeMap
constructor to define the sorting order for the keys.
import java.util.Map;
import java.util.TreeMap;
public class ComparatorExample {
public static void main(String[] args) {
Map<Student, String> studentMap = new TreeMap<>(new SortByGPA());
studentMap.put(new Student(101, "Alice", 3.8), "Math");
studentMap.put(new Student(102, "Bob", 3.6), "Science");
studentMap.put(new Student(103, "Charlie", 3.9), "English");
System.out.println("Sorted map by GPA: " + studentMap);
}
}
In this example, the TreeMap
is created with the SortByGPA
comparator, ensuring that the Student
objects (used as keys) are stored in ascending order of GPA.
4. Advanced Comparator Techniques
Beyond basic comparator implementations, Java offers several advanced techniques for creating more flexible and powerful comparators. This section explores comparator chaining, reverse ordering, and using lambda expressions for comparators.
4.1. Comparator Chaining
Comparator chaining involves combining multiple comparators to create a complex sorting logic. This is useful when you need to sort objects based on multiple criteria.
The thenComparing()
method in the Comparator
interface allows you to chain comparators. Here’s an example:
import java.util.Comparator;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class ComparatorExample {
public static void main(String[] args) {
List<Student> students = new ArrayList<>();
students.add(new Student(101, "Alice", 3.8));
students.add(new Student(102, "Bob", 3.6));
students.add(new Student(103, "Alice", 3.9));
Comparator<Student> chainedComparator = Comparator.comparing(Student::getName)
.thenComparing(Student::getGpa);
Collections.sort(students, chainedComparator);
System.out.println("Sorted by name then GPA: " + students);
}
}
In this example, the chainedComparator
first compares students by their name and then, if the names are the same, compares them by their GPA.
4.2. Reverse Ordering
Sometimes, you need to sort objects in reverse order. The reversed()
method in the Comparator
interface allows you to easily reverse the order of a comparator.
import java.util.Comparator;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class ComparatorExample {
public static void main(String[] args) {
List<Student> students = new ArrayList<>();
students.add(new Student(101, "Alice", 3.8));
students.add(new Student(102, "Bob", 3.6));
students.add(new Student(103, "Charlie", 3.9));
Comparator<Student> sortByGpa = Comparator.comparing(Student::getGpa);
Comparator<Student> sortByGpaReversed = sortByGpa.reversed();
Collections.sort(students, sortByGpaReversed);
System.out.println("Sorted by GPA in reverse order: " + students);
}
}
In this example, the sortByGpaReversed
comparator sorts the students in descending order of their GPA.
4.3. Using Lambda Expressions for Comparators
Lambda expressions provide a concise way to create comparators, especially for simple comparison logic.
import java.util.Comparator;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class ComparatorExample {
public static void main(String[] args) {
List<Student> students = new ArrayList<>();
students.add(new Student(101, "Alice", 3.8));
students.add(new Student(102, "Bob", 3.6));
students.add(new Student(103, "Charlie", 3.9));
Comparator<Student> sortByGpa = (s1, s2) -> Double.compare(s1.getGpa(), s2.getGpa());
Collections.sort(students, sortByGpa);
System.out.println("Sorted by GPA using lambda: " + students);
}
}
In this example, the lambda expression (s1, s2) -> Double.compare(s1.getGpa(), s2.getGpa())
defines a comparator that compares students based on their GPA.
5. Real-World Applications of Comparators
Comparators are used in a wide range of applications where sorting and ordering of objects are required. This section explores some real-world scenarios where comparators are particularly useful.
5.1. Sorting Data in E-Commerce Applications
In e-commerce applications, comparators can be used to sort products based on various criteria, such as price, rating, popularity, and relevance.
For example, you can create comparators to sort products by:
- Price (ascending or descending)
- Customer rating (highest to lowest)
- Number of sales (most to least)
- Date added (newest to oldest)
import java.util.Comparator;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
class Product {
private int id;
private String name;
private double price;
private double rating;
public Product(int id, String name, double price, double rating) {
this.id = id;
this.name = name;
this.price = price;
this.rating = rating;
}
public int getId() {
return id;
}
public String getName() {
return name;
}
public double getPrice() {
return price;
}
public double getRating() {
return rating;
}
@Override
public String toString() {
return "Product{" +
"id=" + id +
", name='" + name + ''' +
", price=" + price +
", rating=" + rating +
'}';
}
}
public class ComparatorExample {
public static void main(String[] args) {
List<Product> products = new ArrayList<>();
products.add(new Product(1, "Laptop", 1200.0, 4.5));
products.add(new Product(2, "Smartphone", 800.0, 4.2));
products.add(new Product(3, "Tablet", 300.0, 4.8));
Comparator<Product> sortByPrice = Comparator.comparing(Product::getPrice);
Comparator<Product> sortByRating = Comparator.comparing(Product::getRating).reversed();
Collections.sort(products, sortByPrice);
System.out.println("Sorted by price: " + products);
Collections.sort(products, sortByRating);
System.out.println("Sorted by rating: " + products);
}
}
5.2. Ordering Search Results
In search applications, comparators can be used to order search results based on relevance, date, or other criteria.
For example, you can create comparators to sort search results by:
- Relevance score (highest to lowest)
- Date modified (newest to oldest)
- Number of views (most to least)
import java.util.Comparator;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
class SearchResult {
private String title;
private String url;
private double relevance;
private String dateModified;
public SearchResult(String title, String url, double relevance, String dateModified) {
this.title = title;
this.url = url;
this.relevance = relevance;
this.dateModified = dateModified;
}
public String getTitle() {
return title;
}
public String getUrl() {
return url;
}
public double getRelevance() {
return relevance;
}
public String getDateModified() {
return dateModified;
}
@Override
public String toString() {
return "SearchResult{" +
"title='" + title + ''' +
", url='" + url + ''' +
", relevance=" + relevance +
", dateModified='" + dateModified + ''' +
'}';
}
}
public class ComparatorExample {
public static void main(String[] args) {
List<SearchResult> searchResults = new ArrayList<>();
searchResults.add(new SearchResult("Java Tutorial", "java.com", 0.8, "2023-01-01"));
searchResults.add(new SearchResult("Java Examples", "example.com", 0.9, "2023-02-01"));
searchResults.add(new SearchResult("Java Documentation", "docs.com", 0.7, "2023-03-01"));
Comparator<SearchResult> sortByRelevance = Comparator.comparing(SearchResult::getRelevance).reversed();
Collections.sort(searchResults, sortByRelevance);
System.out.println("Sorted by relevance: " + searchResults);
}
}
5.3. Sorting Data in Financial Applications
In financial applications, comparators can be used to sort transactions, portfolios, and other financial data based on various criteria, such as date, amount, and type.
For example, you can create comparators to sort transactions by:
- Date (oldest to newest or newest to oldest)
- Amount (highest to lowest or lowest to highest)
- Type (e.g., credit, debit)
import java.util.Comparator;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
class Transaction {
private int id;
private String date;
private double amount;
private String type;
public Transaction(int id, String date, double amount, String type) {
this.id = id;
this.date = date;
this.amount = amount;
this.type = type;
}
public int getId() {
return id;
}
public String getDate() {
return date;
}
public double getAmount() {
return amount;
}
public String getType() {
return type;
}
@Override
public String toString() {
return "Transaction{" +
"id=" + id +
", date='" + date + ''' +
", amount=" + amount +
", type='" + type + ''' +
'}';
}
}
public class ComparatorExample {
public static void main(String[] args) {
List<Transaction> transactions = new ArrayList<>();
transactions.add(new Transaction(1, "2023-01-01", 100.0, "credit"));
transactions.add(new Transaction(2, "2023-02-01", 200.0, "debit"));
transactions.add(new Transaction(3, "2023-03-01", 150.0, "credit"));
Comparator<Transaction> sortByDate = Comparator.comparing(Transaction::getDate);
Comparator<Transaction> sortByAmount = Comparator.comparing(Transaction::getAmount).reversed();
Collections.sort(transactions, sortByDate);
System.out.println("Sorted by date: " + transactions);
Collections.sort(transactions, sortByAmount);
System.out.println("Sorted by amount: " + transactions);
}
}
6. Comparator Interface and Its Methods
The Comparator
interface in Java is a powerful tool for defining custom sorting logic. Understanding its methods and how to use them effectively is essential for leveraging its capabilities. This section delves into the key methods of the Comparator
interface and provides examples of their usage.
6.1. compare(T o1, T o2)
Method
The compare(T o1, T o2)
method is the core of the Comparator
interface. It compares two objects and returns an integer value indicating their relative order. The return value should be:
- Negative if
o1
is less thano2
. - Zero if
o1
is equal too2
. - Positive if
o1
is greater thano2
.
Here’s an example of how to use the compare()
method to sort a list of Employee
objects by their salary:
import java.util.Comparator;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
class Employee {
private int id;
private String name;
private double salary;
public Employee(int id, String name, double salary) {
this.id = id;
this.name = name;
this.salary = salary;
}
public int getId() {
return id;
}
public String getName() {
return name;
}
public double getSalary() {
return salary;
}
@Override
public String toString() {
return "Employee{" +
"id=" + id +
", name='" + name + ''' +
", salary=" + salary +
'}';
}
}
public class ComparatorExample {
public static void main(String[] args) {
List<Employee> employees = new ArrayList<>();
employees.add(new Employee(1, "Alice", 50000.0));
employees.add(new Employee(2, "Bob", 60000.0));
employees.add(new Employee(3, "Charlie", 55000.0));
Comparator<Employee> sortBySalary = new Comparator<Employee>() {
@Override
public int compare(Employee e1, Employee e2) {
return Double.compare(e1.getSalary(), e2.getSalary());
}
};
Collections.sort(employees, sortBySalary);
System.out.println("Sorted by salary: " + employees);
}
}
6.2. reversed()
Method
The reversed()
method returns a comparator that imposes the reverse ordering of the original comparator. This is useful when you need to sort objects in descending order instead of ascending order.
import java.util.Comparator;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class ComparatorExample {
public static void main(String[] args) {
List<Employee> employees = new ArrayList<>();
employees.add(new Employee(1, "Alice", 50000.0));
employees.add(new Employee(2, "Bob", 60000.0));
employees.add(new Employee(3, "Charlie", 55000.0));
Comparator<Employee> sortBySalary = Comparator.comparing(Employee::getSalary);
Comparator<Employee> sortBySalaryReversed = sortBySalary.reversed();
Collections.sort(employees, sortBySalaryReversed);
System.out.println("Sorted by salary in reverse order: " + employees);
}
}
6.3. thenComparing(Comparator<? super T> other)
Method
The thenComparing(Comparator<? super T> other)
method is used to chain multiple comparators together. It returns a new comparator that first uses the original comparator to compare objects, and then uses the specified comparator to compare objects that are equal according to the original comparator.
import java.util.Comparator;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class ComparatorExample {
public static void main(String[] args) {
List<Employee> employees = new ArrayList<>();
employees.add(new Employee(1, "Alice", 50000.0));
employees.add(new Employee(2, "Bob", 60000.0));
employees.add(new Employee(3, "Alice", 55000.0));
Comparator<Employee> sortByNameThenSalary = Comparator.comparing(Employee::getName)
.thenComparing(Employee::getSalary);
Collections.sort(employees, sortByNameThenSalary);
System.out.println("Sorted by name then salary: " + employees);
}
}
6.4. comparing(Function<? super T, ? extends U> keyExtractor)
Method
The comparing(Function<? super T, ? extends U> keyExtractor)
method returns a comparator that compares objects based on the result of applying the specified key extractor function. This is a convenient way to create comparators for specific fields or properties of an object.
import java.util.Comparator;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.function.Function;
public class ComparatorExample {
public static void main(String[] args) {
List<Employee> employees = new ArrayList<>();
employees.add(new Employee(1, "Alice", 50000.0));
employees.add(new Employee(2, "Bob", 60000.0));
employees.add(new Employee(3, "Charlie", 55000.0));
Comparator<Employee> sortByName = Comparator.comparing(Employee::getName);
Collections.sort(employees, sortByName);
System.out.println("Sorted by name: " + employees);
}
}
6.5. nullsFirst(Comparator<? super T> comparator)
and nullsLast(Comparator<? super T> comparator)
Methods
The nullsFirst(Comparator<? super T> comparator)
and nullsLast(Comparator<? super T> comparator)
methods return comparators that handle null values. nullsFirst
places null values at the beginning of the sorted list, while nullsLast
places them at the end.
import java.util.Comparator;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class ComparatorExample {
public static void main(String[] args) {
List<Employee> employees = new ArrayList<>();
employees.add(new Employee(1, "Alice", 50000.0));
employees.add(new Employee(2, "Bob", 60000.0));
employees.add(null);
employees.add(new Employee(3, "Charlie", 55000.0));
Comparator<Employee> sortByName = Comparator.comparing(Employee::getName, Comparator.nullsFirst(String::compareTo));
Collections.sort(employees, sortByName);
System.out.println("Sorted by name with nulls first: " + employees);
}
}
7. Common Pitfalls and How to Avoid Them
When working with comparators, it’s easy to make mistakes that can lead to unexpected behavior or errors. This section outlines some common pitfalls and provides strategies for avoiding them.
7.1. Inconsistent Comparison Logic
One of the most common pitfalls is implementing comparison logic that is inconsistent or violates the contract of the Comparator
interface. The compare()
method must be transitive, symmetric, and consistent.
- Transitivity: If
compare(a, b) > 0
andcompare(b, c) > 0
, thencompare(a, c) > 0
. - Symmetry: If
compare(a, b) == 0
, thencompare(b, a) == 0
. - Consistency: Multiple invocations of
compare(a, b)
should consistently return the same result, provided that the objectsa
andb
have not been modified.
To avoid inconsistent comparison logic, carefully review your implementation and ensure that it adheres to these principles. Use unit tests to verify that your comparator behaves correctly in various scenarios.
7.2. Handling Null Values Incorrectly
Failing to handle null values correctly can lead to NullPointerException
or incorrect sorting results. Always check for null values in your compare()
method and handle them appropriately.
public int compare(Student s1, Student s2) {
if (s1 == null && s2 == null) return 0;
if (s1 == null) return -1;
if (s2 == null) return 1;
return Integer.compare(s1.getId(), s2.getId());
}
Alternatively, you can use the Comparator.nullsFirst()
or Comparator.nullsLast()
methods to handle null values.
7.3. Performance Issues
Complex comparison logic can lead to performance issues, especially when sorting large collections. Avoid performing expensive operations in your compare()
method, such as database lookups or complex calculations.
Instead, pre-compute the values needed for comparison and store them in the object. This can significantly improve the performance of your comparator.
7.4. Not Implementing Serializable
If your comparator is used in serializable data structures, such as TreeSet
or TreeMap
, it must also implement the Serializable
interface. Otherwise, you may encounter NotSerializableException
when attempting to serialize the data structure.
import java.io.Serializable;
import java.util.Comparator;
class SortByGPA implements Comparator<Student>, Serializable {
@Override
public int compare(Student s1, Student s2) {
return Double.compare(s1.getGpa(), s2.getGpa());
}
}
8. Benefits of Using Comparators
Using comparators in Java offers several benefits, including increased flexibility, code reusability, and improved maintainability. This section highlights the key advantages of using comparators in your Java applications.
8.1. Flexibility in Sorting
Comparators provide a high degree of flexibility in sorting objects. You can define multiple comparators for the same class, each providing a different sorting strategy. This allows you to sort objects based on various criteria without modifying the original class.
import java.util.Comparator;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class ComparatorExample {
public static void main(String[] args) {
List<Student> students = new ArrayList<>();
students.add(new Student(101, "Alice", 3.8));
students.add(new Student(102, "Bob", 3.6));
students.add(new Student(103, "Charlie", 3.9));
Comparator<Student> sortByName = Comparator.comparing(Student::getName);
Comparator<Student> sortByGPA = Comparator.comparing(Student::getGpa);
Collections.sort(students, sortByName);
System.out.println("Sorted by name: " + students);
Collections.sort(students, sortByGPA);
System.out.println("Sorted by GPA: " + students);
}
}
8.2. Code Reusability
Comparators can be reused across multiple classes and applications. Once you define a comparator, you can use it to sort objects in any collection that contains objects of the same type. This promotes code reusability and reduces the amount of code you need to write.
import java.util.Comparator;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class ComparatorExample {
public static void main(String[] args) {
List<Student> students = new ArrayList<>();
students.add(new Student(101, "Alice", 3.8));
students.add(new Student(102, "Bob", 3.6));
students.add(new Student(103, "Charlie", 3.9));
List<Employee> employees = new ArrayList<>();
employees.add(new Employee(1, "Alice", 50000.0));
employees.add(new Employee(2, "Bob", 60000.0));
employees.add(new Employee(3, "Charlie", 55000.0));
Comparator<String> sortByName = String::compareTo;
Collections.sort(students, (s1, s2) -> sortByName.compare(s1.getName(), s2.getName()));
System.out.println("Sorted students by name: " + students);
Collections.sort(employees, (e1, e2) -> sortByName.compare(e1.getName(), e2.getName()));
System.out.println("Sorted employees by name: " + employees);
}
}
8.3. Improved Maintainability
Comparators improve the maintainability of your code by separating the sorting logic from the class being sorted. This makes it easier to update or modify the sorting logic without affecting the rest of the code.
import java.util.Comparator;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class ComparatorExample {
public static void main(String[] args) {
List<Student> students