Comparable and Comparator are crucial interfaces in Java for sorting objects, and COMPARE.EDU.VN can help you understand their differences and usage. This article explores how to use them effectively with examples, covering custom sorting, natural ordering, and implementation details, ensuring you grasp the nuances of Java sorting mechanisms. Dive into effective data comparison, object sorting strategies, and advanced sorting techniques to elevate your Java programming skills.
1. What Are Comparable And Comparator In Java?
Comparable and Comparator are two fundamental interfaces in Java used for sorting objects. Comparable defines a natural order for objects within a class, while Comparator defines custom sorting logic externally. Understanding these interfaces is crucial for efficient data manipulation and organization in Java applications, and COMPARE.EDU.VN provides detailed comparisons to guide your choices.
1.1 What Is Comparable?
Comparable is an interface that defines a natural ordering for objects of a class. A class implements the Comparable interface to provide a way to compare its instances, allowing them to be sorted automatically using methods like Collections.sort()
or Arrays.sort()
. The Comparable interface includes a single method, compareTo()
, which determines the order of two objects.
1.1.1 How to Implement Comparable
To implement the Comparable interface, a class must:
- Declare that it implements the
Comparable
interface. - Implement the
compareTo(T o)
method.
The compareTo()
method returns:
- A negative integer if the current object is less than the argument object.
- A positive integer if the current object is greater than the argument object.
- Zero if the current object is equal to the argument object.
Here’s an example of a Student
class implementing the Comparable
interface to sort students by their ID:
class Student implements Comparable<Student> {
private int id;
private String name;
public Student(int id, String name) {
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public String getName() {
return name;
}
@Override
public int compareTo(Student other) {
return Integer.compare(this.id, other.id);
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + ''' +
'}';
}
public static void main(String[] args) {
List<Student> students = new ArrayList<>();
students.add(new Student(3, "Alice"));
students.add(new Student(1, "Bob"));
students.add(new Student(2, "Charlie"));
Collections.sort(students);
students.forEach(System.out::println);
}
}
In this example, the compareTo()
method compares the id
of two Student
objects, allowing the Collections.sort()
method to sort the list of students by their IDs in ascending order.
1.1.2 Advantages of Using Comparable
- Natural Ordering: Provides a default way to sort objects.
- Simplicity: Easy to implement within the class itself.
- Integration: Works seamlessly with Java’s sorting methods.
1.1.3 Disadvantages of Using Comparable
- Single Sorting Order: Only one sorting order can be defined.
- Class Modification: Requires modification of the class to implement the interface.
1.2 What Is Comparator?
Comparator is an interface that defines a custom sorting logic externally to the class. It allows you to define multiple sorting orders for the same class without modifying the class itself. The Comparator interface includes a single method, compare()
, which determines the order of two objects.
1.2.1 How to Implement Comparator
To implement the Comparator interface, you need to:
- Create a separate class that implements the
Comparator
interface. - Implement the
compare(T o1, T o2)
method.
The compare()
method returns:
- A negative integer if the first object is less than the second object.
- A positive integer if the first object is greater than the second object.
- Zero if the first object is equal to the second object.
Here’s an example of using a Comparator to sort a list of Student
objects by name:
class Student {
private int id;
private String name;
public Student(int id, String name) {
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public String getName() {
return name;
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + ''' +
'}';
}
}
class SortByName implements Comparator<Student> {
@Override
public int compare(Student a, Student b) {
return a.getName().compareTo(b.getName());
}
public static void main(String[] args) {
List<Student> students = new ArrayList<>();
students.add(new Student(3, "Alice"));
students.add(new Student(1, "Bob"));
students.add(new Student(2, "Charlie"));
Collections.sort(students, new SortByName());
students.forEach(System.out::println);
}
}
In this example, the SortByName
class implements the Comparator
interface and provides a custom sorting logic based on the name
of the Student
objects. The Collections.sort()
method is then used with an instance of SortByName
to sort the list of students by name.
1.2.2 Advantages of Using Comparator
- Multiple Sorting Orders: Allows defining multiple sorting orders for the same class.
- No Class Modification: Does not require modification of the class itself.
- Flexibility: Provides greater flexibility in defining sorting logic.
1.2.3 Disadvantages of Using Comparator
- Extra Class: Requires creating a separate class for each sorting order.
- Complexity: Can be more complex to implement compared to Comparable.
1.3 Key Differences Between Comparable and Comparator
Feature | Comparable | Comparator |
---|---|---|
Definition | Defines natural ordering within the class. | Defines external or custom sorting logic. |
Method | compareTo() |
compare() |
Implementation | Implemented in the class. | Implemented in a separate class. |
Sorting Criteria | Natural order sorting. | Custom order sorting. |
Usage | Used for a single sorting order. | Used for multiple sorting orders. |
Modification | Requires class modification. | Does not require class modification. |
Flexibility | Less flexible. | More flexible. |
1.4 When to Use Comparable vs. Comparator
Choosing between Comparable and Comparator depends on your specific needs:
- Use Comparable when you want to define a natural ordering for objects of a class and only need one sorting order.
- Use Comparator when you need multiple sorting orders for the same class or when you cannot modify the class itself.
Understanding these differences helps in making the right choice for sorting objects in Java, and COMPARE.EDU.VN offers additional insights to refine your approach.
2. How To Implement Comparable Interface In Java?
Implementing the Comparable interface in Java involves defining a natural ordering for objects of a class. This section provides a step-by-step guide on how to implement the Comparable interface, along with practical examples.
2.1 Steps to Implement Comparable
- Declare the Implementation:
- Modify the class declaration to include
implements Comparable<YourClass>
.
- Modify the class declaration to include
- Implement the
compareTo()
Method:- Provide an implementation for the
compareTo(T o)
method. - This method should compare the current object with the specified object and return a negative integer, zero, or a positive integer based on whether the current object is less than, equal to, or greater than the specified object.
- Provide an implementation for the
- Define the Sorting Logic:
- Within the
compareTo()
method, define the logic for comparing objects based on one or more attributes. - Ensure that the comparison logic is consistent and follows the contract of the Comparable interface.
- Within the
2.2 Example: Sorting Employees by Salary
Consider an Employee
class that needs to be sorted by salary. Here’s how to implement the Comparable interface:
class Employee implements Comparable<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 int compareTo(Employee other) {
return Double.compare(this.salary, other.salary);
}
@Override
public String toString() {
return "Employee{" +
"id=" + id +
", name='" + name + ''' +
", salary=" + salary +
'}';
}
public static void main(String[] args) {
List<Employee> employees = new ArrayList<>();
employees.add(new Employee(1, "Alice", 50000));
employees.add(new Employee(2, "Bob", 60000));
employees.add(new Employee(3, "Charlie", 40000));
Collections.sort(employees);
employees.forEach(System.out::println);
}
}
In this example, the compareTo()
method compares the salary
of two Employee
objects, allowing the Collections.sort()
method to sort the list of employees by their salaries in ascending order.
2.3 Best Practices for Implementing Comparable
- Consistency: Ensure that the comparison logic is consistent and follows the contract of the Comparable interface.
- Null Handling: Handle null values appropriately to avoid NullPointerException.
- Immutability: If possible, make the attributes used for comparison immutable.
2.4 Advanced Comparable Techniques
- Chaining Comparisons: Combine multiple attributes for comparison.
- Reverse Ordering: Use the reverse order by negating the result of the comparison.
Implementing the Comparable interface effectively allows you to define a natural ordering for objects in Java, facilitating easy sorting and comparison, and COMPARE.EDU.VN offers additional examples and best practices to enhance your implementation skills.
3. How To Implement Comparator Interface In Java?
Implementing the Comparator interface in Java allows you to define custom sorting logic externally to the class. This section provides a detailed guide on how to implement the Comparator interface, complete with examples.
3.1 Steps to Implement Comparator
- Create a Comparator Class:
- Create a new class that implements the
Comparator<YourClass>
interface.
- Create a new class that implements the
- Implement the
compare()
Method:- Provide an implementation for the
compare(T o1, T o2)
method. - This method should compare the two objects and return a negative integer, zero, or a positive integer based on whether the first object is less than, equal to, or greater than the second object.
- Provide an implementation for the
- Define the Sorting Logic:
- Within the
compare()
method, define the logic for comparing objects based on one or more attributes. - Ensure that the comparison logic is consistent and adheres to the contract of the Comparator interface.
- Within the
- Use the Comparator:
- Pass an instance of the Comparator class to the
Collections.sort()
method or other sorting methods that accept a Comparator.
- Pass an instance of the Comparator class to the
3.2 Example: Sorting Products by Price and Name
Consider a Product
class that can be sorted by price or name. Here’s how to implement the Comparator interface to achieve this:
class Product {
private int id;
private String name;
private double price;
public Product(int id, String name, double price) {
this.id = id;
this.name = name;
this.price = price;
}
public int getId() {
return id;
}
public String getName() {
return name;
}
public double getPrice() {
return price;
}
@Override
public String toString() {
return "Product{" +
"id=" + id +
", name='" + name + ''' +
", price=" + price +
'}';
}
}
class SortByPrice implements Comparator<Product> {
@Override
public int compare(Product a, Product b) {
return Double.compare(a.getPrice(), b.getPrice());
}
}
class SortByName implements Comparator<Product> {
@Override
public int compare(Product a, Product b) {
return a.getName().compareTo(b.getName());
}
}
public class Main {
public static void main(String[] args) {
List<Product> products = new ArrayList<>();
products.add(new Product(1, "Laptop", 1200));
products.add(new Product(2, "Tablet", 300));
products.add(new Product(3, "Phone", 800));
System.out.println("Sorting by Price:");
Collections.sort(products, new SortByPrice());
products.forEach(System.out::println);
System.out.println("nSorting by Name:");
Collections.sort(products, new SortByName());
products.forEach(System.out::println);
}
}
In this example:
- The
SortByPrice
class implements theComparator
interface to sort products by their prices. - The
SortByName
class implements theComparator
interface to sort products by their names. - The
Collections.sort()
method is used with instances of these Comparators to sort the list of products accordingly.
3.3 Best Practices for Implementing Comparator
- Clarity: Ensure that the comparison logic is clear and easy to understand.
- Immutability: If possible, use immutable attributes for comparison.
- Consistency: Maintain consistency in the comparison results.
3.4 Advanced Comparator Techniques
- Chaining Comparators: Combine multiple Comparators for complex sorting.
- Using Lambda Expressions: Implement Comparators using lambda expressions for concise code.
Implementing the Comparator interface effectively allows you to define custom sorting logic for objects in Java, providing flexibility and control over the sorting process, and COMPARE.EDU.VN offers additional insights to refine your approach.
4. Comparable vs Comparator: Choosing The Right Interface
Choosing between the Comparable and Comparator interfaces in Java depends on the specific requirements of your application. This section outlines the key considerations to help you decide which interface is most appropriate for your sorting needs.
4.1 Key Considerations
- Natural Ordering vs. Custom Ordering:
- Use Comparable when you want to define a natural ordering for objects of a class. This is suitable when there is a single, obvious way to sort the objects.
- Use Comparator when you need multiple sorting orders for the same class or when you cannot modify the class itself.
- Class Modification:
- Comparable requires modification of the class to implement the interface.
- Comparator does not require modification of the class, as it is implemented in a separate class.
- Number of Sorting Orders:
- Comparable is suitable for a single sorting order.
- Comparator allows defining multiple sorting orders.
- Flexibility:
- Comparator provides greater flexibility in defining sorting logic.
- Comparable is less flexible, as it only allows one sorting order.
4.2 Scenarios for Using Comparable
- Simple Sorting Requirements: When you need a default way to sort objects and the sorting logic is straightforward.
- Single Attribute Sorting: When you want to sort objects based on a single attribute.
- When You Control the Class: When you have the ability to modify the class to implement the Comparable interface.
4.3 Scenarios for Using Comparator
- Complex Sorting Requirements: When you need to sort objects based on multiple criteria or custom logic.
- Multiple Sorting Orders: When you need to sort objects in different ways at different times.
- When You Cannot Modify the Class: When you cannot modify the class to implement the Comparable interface, such as when using third-party libraries.
4.4 Example: Choosing Between Comparable and Comparator
Consider a Book
class that needs to be sorted. If you want to define a natural ordering for books based on their titles, you can implement the Comparable interface. However, if you also need to sort books by their authors or publication dates, you should use the Comparator interface.
class Book implements Comparable<Book> {
private int id;
private String title;
private String author;
private int publicationYear;
public Book(int id, String title, String author, int publicationYear) {
this.id = id;
this.title = title;
this.author = author;
this.publicationYear = publicationYear;
}
public int getId() {
return id;
}
public String getTitle() {
return title;
}
public String getAuthor() {
return author;
}
public int getPublicationYear() {
return publicationYear;
}
@Override
public int compareTo(Book other) {
return this.title.compareTo(other.title);
}
@Override
public String toString() {
return "Book{" +
"id=" + id +
", title='" + title + ''' +
", author='" + author + ''' +
", publicationYear=" + publicationYear +
'}';
}
}
class SortByAuthor implements Comparator<Book> {
@Override
public int compare(Book a, Book b) {
return a.getAuthor().compareTo(b.getAuthor());
}
}
class SortByPublicationYear implements Comparator<Book> {
@Override
public int compare(Book a, Book b) {
return Integer.compare(a.getPublicationYear(), b.getPublicationYear());
}
}
public class Main {
public static void main(String[] args) {
List<Book> books = new ArrayList<>();
books.add(new Book(1, "The Great Gatsby", "F. Scott Fitzgerald", 1925));
books.add(new Book(2, "To Kill a Mockingbird", "Harper Lee", 1960));
books.add(new Book(3, "1984", "George Orwell", 1949));
System.out.println("Sorting by Title:");
Collections.sort(books);
books.forEach(System.out::println);
System.out.println("nSorting by Author:");
Collections.sort(books, new SortByAuthor());
books.forEach(System.out::println);
System.out.println("nSorting by Publication Year:");
Collections.sort(books, new SortByPublicationYear());
books.forEach(System.out::println);
}
}
In this example:
- The
Book
class implements the Comparable interface to sort books by their titles. - The
SortByAuthor
andSortByPublicationYear
classes implement the Comparator interface to sort books by their authors and publication years, respectively.
4.5 Best Practices for Choosing an Interface
- Start with Comparable: If you need a natural ordering for objects and you control the class, start with the Comparable interface.
- Use Comparator for Flexibility: If you need multiple sorting orders or you cannot modify the class, use the Comparator interface.
- Consider Future Requirements: Think about future sorting requirements when choosing an interface.
By carefully considering these factors, you can choose the most appropriate interface for your sorting needs in Java, and COMPARE.EDU.VN provides additional insights to refine your decision-making process.
5. Practical Examples Of Comparable And Comparator In Java
This section provides practical examples of using Comparable and Comparator in Java to sort different types of objects. These examples illustrate how to implement and use these interfaces in real-world scenarios.
5.1 Example 1: Sorting Students by Multiple Criteria
Consider a Student
class with attributes like id
, name
, and grade
. You can use Comparator to sort students by multiple criteria, such as grade and name.
class Student {
private int id;
private String name;
private double grade;
public Student(int id, String name, double grade) {
this.id = id;
this.name = name;
this.grade = grade;
}
public int getId() {
return id;
}
public String getName() {
return name;
}
public double getGrade() {
return grade;
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + ''' +
", grade=" + grade +
'}';
}
}
class SortByGrade implements Comparator<Student> {
@Override
public int compare(Student a, Student b) {
return Double.compare(b.getGrade(), a.getGrade()); // Sort in descending order
}
}
class SortByName implements Comparator<Student> {
@Override
public int compare(Student a, Student b) {
return a.getName().compareTo(b.getName());
}
}
public class Main {
public static void main(String[] args) {
List<Student> students = new ArrayList<>();
students.add(new Student(1, "Alice", 85.0));
students.add(new Student(2, "Bob", 90.0));
students.add(new Student(3, "Charlie", 85.0));
System.out.println("Sorting by Grade (Descending):");
Collections.sort(students, new SortByGrade());
students.forEach(System.out::println);
System.out.println("nSorting by Name:");
Collections.sort(students, new SortByName());
students.forEach(System.out::println);
}
}
In this example:
- The
SortByGrade
class implements theComparator
interface to sort students by their grades in descending order. - The
SortByName
class implements theComparator
interface to sort students by their names. - The
Collections.sort()
method is used with instances of these Comparators to sort the list of students accordingly.
5.2 Example 2: Sorting Dates Using Comparable
Consider a Date
class that needs to be sorted. You can implement the Comparable interface to define a natural ordering for dates.
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
class Date implements Comparable<Date> {
private LocalDate date;
public Date(LocalDate date) {
this.date = date;
}
public LocalDate getDate() {
return date;
}
@Override
public int compareTo(Date other) {
return this.date.compareTo(other.date);
}
@Override
public String toString() {
return "Date{" +
"date=" + date +
'}';
}
public static void main(String[] args) {
List<Date> dates = new ArrayList<>();
dates.add(new Date(LocalDate.of(2023, 1, 1)));
dates.add(new Date(LocalDate.of(2022, 12, 31)));
dates.add(new Date(LocalDate.of(2023, 2, 1)));
Collections.sort(dates);
dates.forEach(System.out::println);
}
}
In this example:
- The
Date
class implements the Comparable interface to sort dates. - The
compareTo()
method compares thedate
of twoDate
objects, allowing theCollections.sort()
method to sort the list of dates in ascending order.
5.3 Example 3: Sorting Products by Price Using Comparator with Lambda Expressions
Consider a Product
class that needs to be sorted by price. You can use Comparator with lambda expressions for a concise implementation.
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
class Product {
private int id;
private String name;
private double price;
public Product(int id, String name, double price) {
this.id = id;
this.name = name;
this.price = price;
}
public int getId() {
return id;
}
public String getName() {
return name;
}
public double getPrice() {
return price;
}
@Override
public String toString() {
return "Product{" +
"id=" + id +
", name='" + name + ''' +
", price=" + price +
'}';
}
}
public class Main {
public static void main(String[] args) {
List<Product> products = new ArrayList<>();
products.add(new Product(1, "Laptop", 1200));
products.add(new Product(2, "Tablet", 300));
products.add(new Product(3, "Phone", 800));
System.out.println("Sorting by Price:");
Collections.sort(products, (a, b) -> Double.compare(a.getPrice(), b.getPrice()));
products.forEach(System.out::println);
}
}
In this example:
- A lambda expression is used to implement the Comparator interface inline, sorting products by their prices.
- The
Collections.sort()
method is used with the lambda expression to sort the list of products.
5.4 Best Practices for Implementing Sorting
- Choose the Right Interface: Select Comparable for natural ordering and Comparator for custom sorting.
- Keep Comparison Logic Clear: Ensure that the comparison logic is easy to understand and maintain.
- Handle Edge Cases: Handle null values and other edge cases appropriately.
- Use Lambda Expressions for Conciseness: Use lambda expressions for concise Comparator implementations.
These practical examples illustrate how to effectively use Comparable and Comparator in Java for various sorting scenarios, and compare.edu.vn provides additional resources to deepen your understanding and skills.
6. Advanced Sorting Techniques With Comparator And Comparable
This section explores advanced sorting techniques using Comparator and Comparable in Java. These techniques provide more control and flexibility over the sorting process, allowing you to handle complex sorting scenarios.
6.1 Chaining Comparators
Chaining Comparators involves combining multiple Comparators to sort objects based on multiple criteria. This technique is useful when you need to sort objects by one attribute and then, within each group, sort by another attribute.
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
class Employee {
private int id;
private String name;
private double salary;
private int age;
public Employee(int id, String name, double salary, int age) {
this.id = id;
this.name = name;
this.salary = salary;
this.age = age;
}
public int getId() {
return id;
}
public String getName() {
return name;
}
public double getSalary() {
return salary;
}
public int getAge() {
return age;
}
@Override
public String toString() {
return "Employee{" +
"id=" + id +
", name='" + name + ''' +
", salary=" + salary +
", age=" + age +
'}';
}
}
class SortBySalary implements Comparator<Employee> {
@Override
public int compare(Employee a, Employee b) {
return Double.compare(b.getSalary(), a.getSalary()); // Sort in descending order
}
}
class SortByName implements Comparator<Employee> {
@Override
public int compare(Employee a, Employee b) {
return a.getName().compareTo(b.getName());
}
}
public class Main {
public static void main(String[] args) {
List<Employee> employees = new ArrayList<>();
employees.add(new Employee(1, "Alice", 50000, 30));
employees.add(new Employee(2, "Bob", 60000, 25));
employees.add(new Employee(3, "Charlie", 50000, 35));
System.out.println("Sorting by Salary (Descending) then by Name:");
employees.sort(Comparator.comparing(Employee::getSalary).reversed().thenComparing(Employee::getName));
employees.forEach(System.out::println);
}
}
In this example:
- The
employees
are first sorted bysalary
in descending order and then byname
in ascending order within each salary group. - The
Comparator.comparing()
method is used to create Comparators forsalary
andname
. - The
reversed()
method is used to sort the salary in descending order. - The
thenComparing()
method is used to chain the Comparators, sorting by name within each salary group.
6.2 Using Lambda Expressions for Complex Sorting
Lambda expressions provide a concise way to implement Comparators for complex sorting scenarios. This technique is particularly useful when you need to define custom sorting logic inline.
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
class Product {
private int id;
private String name;
private double price;
private int quantity;
public Product(int id, String name, double price, int quantity) {
this.id = id;
this.name = name;
this.price = price;
this.quantity = quantity;
}
public int getId() {
return id;
}
public String getName() {
return name;
}
public double getPrice() {
return price;
}
public int getQuantity() {
return quantity;
}
@Override
public String toString() {
return "Product{" +
"id=" + id +
", name='" + name + ''' +
", price=" + price +
", quantity=" + quantity +
'}';
}
}
public class Main {
public static void main(String[] args) {
List<Product> products = new ArrayList<>();
products.add(new Product(1, "Laptop", 1200, 5));
products.add(new Product(2, "Tablet", 300, 10));
products.add(new Product(3, "Phone", 800, 7));
System.out.println("Sorting by Price then by Quantity:");
Collections.sort(products, (a, b) -> {
int priceComparison = Double.compare(a.getPrice(), b.getPrice());
if (priceComparison != 0) {
return priceComparison;
}
return Integer.compare(b.getQuantity(), a.getQuantity()); // Sort quantity in descending order
});
products.forEach(System.out::println);
}
}
In this example:
- The
products
are sorted byprice
in ascending order and then byquantity
in descending order within each price group. - A lambda expression is used to implement the Comparator interface inline, providing custom sorting logic.
- The sorting logic first compares the prices of the products. If the prices are different, it returns the comparison result. Otherwise, it compares the quantities in descending order.
6.3 Custom Sorting with Comparable and Comparator
You can combine Comparable and Comparator to achieve custom sorting scenarios. For example, you can define a natural ordering for objects using Comparable and then use Comparator to override the natural ordering for specific sorting requirements.
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
class Book implements Comparable<Book> {
private int id;
private String title;
private String author;
private int publicationYear;
public Book(int id, String title, String author, int publicationYear) {
this.id = id;
this.title = title;
this.author = author;
this.publicationYear = publicationYear;
}
public int getId() {
return id;
}
public String getTitle() {
return title;
}
public String getAuthor() {
return author;
}
public int getPublicationYear() {
return publicationYear;
}
@Override
public int compareTo(Book other) {
return this.title.compareTo(other.title); // Natural ordering by title
}
@Override
public String toString() {
return "Book{" +
"id=" + id +
", title='" + title + ''' +
", author='" + author + ''' +
", publicationYear=" + publicationYear +
'}';
}
}
class SortByAuthor implements Comparator<Book> {
@Override
public int compare(Book a, Book b) {
return a.getAuthor().compareTo(b.getAuthor());
}
}
public class Main {
public static void main(String[] args) {
List<Book> books = new ArrayList<>();
books.add(new Book(1, "The Great Gatsby", "F. Scott Fitzgerald", 1925));
books.add(new Book(2, "To Kill a Mockingbird", "Harper Lee", 1960));
books.add(new Book(3, "1984", "George Orwell", 1949));
System.out.println("Sorting by Title (Natural Ordering):");
Collections.sort(books); // Uses Comparable (natural ordering by title)
books.forEach(System.out::println);
System.out.println("nSorting by Author (Custom Ordering):");
Collections.sort(books, new SortByAuthor()); // Uses Comparator (custom ordering by author)
books.forEach(System.out::println);
}
}
In this example:
- The
Book
class implements the Comparable interface, providing a natural ordering by title. - The
SortByAuthor
class implements the Comparator interface, providing a