How Do You Use Comparator And Comparable In Java With Example?

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:

  1. Declare that it implements the Comparable interface.
  2. 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:

  1. Create a separate class that implements the Comparator interface.
  2. 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

  1. Declare the Implementation:
    • Modify the class declaration to include implements Comparable<YourClass>.
  2. 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.
  3. 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.

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

  1. Create a Comparator Class:
    • Create a new class that implements the Comparator<YourClass> interface.
  2. 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.
  3. 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.
  4. Use the Comparator:
    • Pass an instance of the Comparator class to the Collections.sort() method or other sorting methods that accept a Comparator.

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 the Comparator interface to sort products by their prices.
  • The SortByName class implements the Comparator 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

  1. 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.
  2. 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.
  3. Number of Sorting Orders:
    • Comparable is suitable for a single sorting order.
    • Comparator allows defining multiple sorting orders.
  4. 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 and SortByPublicationYear 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 the Comparator interface to sort students by their grades in descending order.
  • The SortByName class implements the Comparator 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 the date of two Date objects, allowing the Collections.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 by salary in descending order and then by name in ascending order within each salary group.
  • The Comparator.comparing() method is used to create Comparators for salary and name.
  • 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 by price in ascending order and then by quantity 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

Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply

Your email address will not be published. Required fields are marked *