**How Does Comparator Work In Java? A Comprehensive Guide**

Comparator in Java defines a comparison rule for sorting objects; understanding its mechanism is essential for effective data manipulation. Compare.edu.vn offers detailed comparisons to aid your learning journey.

The Java Comparator is an interface used to define custom sorting logic for objects. If you’re seeking to elevate your Java programming skills, understanding how Comparators function is crucial; compare.edu.vn provides comprehensive guides and comparisons to aid your learning. This article delves into the intricacies of Java Comparators, exploring their purpose, implementation, and benefits for customized sorting. Dive in to master advanced sorting techniques and make your applications more efficient. Explore related concepts like Comparable interface, lambda expressions for comparators, and custom sorting rules.

1. What Is a Comparator in Java?

In Java, a Comparator is an interface that enables you to define a custom comparison logic for objects. This is crucial when you need to sort objects based on criteria other than their natural ordering (defined by the Comparable interface). It provides a flexible way to sort collections of objects according to specific requirements.

1.1. Defining a Comparator

A Comparator is defined by creating a class that implements the java.util.Comparator interface. This interface contains a single method, compare(Object obj1, Object obj2), which you must implement. The compare() method determines the order of two objects.

1.2. The compare() Method

The compare() method takes two objects as input and returns an integer value:

  • Negative: If obj1 should come before obj2.
  • Positive: If obj1 should come after obj2.
  • Zero: If obj1 and obj2 are equal.

1.3. Why Use a Comparator?

Using a Comparator is essential when:

  • You want to sort objects of a class that doesn’t implement the Comparable interface.
  • You need to sort objects based on multiple criteria or different fields.
  • You want to change the sorting behavior without modifying the class itself.

2. Implementing a Comparator in Java: A Step-by-Step Guide

To implement a Comparator in Java, follow these steps:

2.1. Create a Class Implementing the Comparator Interface

First, create a new class that implements the java.util.Comparator interface.

import java.util.Comparator;

class SortByYear implements Comparator<Car> {
    @Override
    public int compare(Car car1, Car car2) {
        // Implementation will go here
    }
}

2.2. Implement the compare() Method

Implement the compare() method to define the sorting logic. For example, let’s sort Car objects by their manufacturing year:

import java.util.Comparator;

class SortByYear implements Comparator<Car> {
    @Override
    public int compare(Car car1, Car car2) {
        return car1.getYear() - car2.getYear();
    }
}

2.3. Use the Comparator

Use the Comparator with sorting methods like Collections.sort() or Arrays.sort().

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        List<Car> cars = new ArrayList<>();
        cars.add(new Car("BMW", "X5", 2019));
        cars.add(new Car("Honda", "Accord", 2022));
        cars.add(new Car("Ford", "Mustang", 2020));

        Collections.sort(cars, new SortByYear());

        for (Car car : cars) {
            System.out.println(car);
        }
    }
}

2.4. Example: Complete Code

Here’s a complete example:

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

class Car {
    private String brand;
    private String model;
    private int year;

    public Car(String brand, String model, int year) {
        this.brand = brand;
        this.model = model;
        this.year = year;
    }

    public String getBrand() {
        return brand;
    }

    public String getModel() {
        return model;
    }

    public int getYear() {
        return year;
    }

    @Override
    public String toString() {
        return "Car{" +
                "brand='" + brand + ''' +
                ", model='" + model + ''' +
                ", year=" + year +
                '}';
    }
}

class SortByYear implements Comparator<Car> {
    @Override
    public int compare(Car car1, Car car2) {
        return car1.getYear() - car2.getYear();
    }
}

public class Main {
    public static void main(String[] args) {
        List<Car> cars = new ArrayList<>();
        cars.add(new Car("BMW", "X5", 2019));
        cars.add(new Car("Honda", "Accord", 2022));
        cars.add(new Car("Ford", "Mustang", 2020));

        Collections.sort(cars, new SortByYear());

        for (Car car : cars) {
            System.out.println(car);
        }
    }
}

3. Using Lambda Expressions with Comparators

Java 8 introduced lambda expressions, which provide a concise way to create Comparators. Lambda expressions are particularly useful for simple, one-off sorting requirements.

3.1. Lambda Expression Syntax

A lambda expression can replace an anonymous class implementation of the Comparator interface. The syntax is:

(parameters) -> { body }

3.2. Example: Sorting with Lambda

Here’s how to sort the Car objects using a lambda expression:

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        List<Car> cars = new ArrayList<>();
        cars.add(new Car("BMW", "X5", 2019));
        cars.add(new Car("Honda", "Accord", 2022));
        cars.add(new Car("Ford", "Mustang", 2020));

        Collections.sort(cars, (car1, car2) -> car1.getYear() - car2.getYear());

        for (Car car : cars) {
            System.out.println(car);
        }
    }
}

3.3. Benefits of Using Lambda

  • Conciseness: Lambda expressions reduce boilerplate code.
  • Readability: They make the code easier to read and understand.
  • Flexibility: They are easy to define inline, directly where they are used.

4. Comparator vs. Comparable: Understanding the Differences

Both Comparator and Comparable are used for sorting objects in Java, but they serve different purposes and are used in different scenarios.

4.1. The Comparable Interface

The Comparable interface is implemented by the class whose objects you want to sort. It provides a natural ordering for the objects.

  • Method: compareTo(Object obj)
  • Purpose: Defines the default way to compare objects of the class.
  • Implementation: Implemented within the class itself.
class Car implements Comparable<Car> {
    private String brand;
    private String model;
    private int year;

    @Override
    public int compareTo(Car other) {
        return this.year - other.year;
    }
}

4.2. The Comparator Interface

The Comparator interface is implemented by a separate class. It provides a way to define custom sorting logic that is external to the class being sorted.

  • Method: compare(Object obj1, Object obj2)
  • Purpose: Defines a custom way to compare two objects.
  • Implementation: Implemented in a separate class.
class SortByBrand implements Comparator<Car> {
    @Override
    public int compare(Car car1, Car car2) {
        return car1.getBrand().compareTo(car2.getBrand());
    }
}

4.3. Key Differences

Feature Comparable Comparator
Implementation Implemented by the class being sorted Implemented by a separate class
Purpose Defines the natural ordering Defines a custom ordering
Number of Orders One natural order per class Multiple custom orders for the same class
Flexibility Less flexible More flexible
Use Case Default sorting based on a single criterion Sorting based on multiple criteria or fields

4.4. When to Use Which

  • Use Comparable when you want to define a default sorting order for objects of a class and you can modify the class.
  • Use Comparator when you want to define custom sorting orders, need to sort objects of a class you cannot modify, or want to provide multiple sorting options.

5. Sorting with Multiple Criteria Using Comparators

One of the powerful features of Comparators is the ability to sort objects based on multiple criteria. This involves creating a Comparator that considers multiple fields when comparing objects.

5.1. Implementing Multi-Criteria Sorting

To sort by multiple criteria, implement the compare() method to compare the primary field first. If the primary fields are equal, then compare the secondary field, and so on.

5.2. Example: Sorting Cars by Brand and Year

Here’s an example of sorting Car objects first by brand and then by year:

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

class Car {
    private String brand;
    private String model;
    private int year;

    public Car(String brand, String model, int year) {
        this.brand = brand;
        this.model = model;
        this.year = year;
    }

    public String getBrand() {
        return brand;
    }

    public String getModel() {
        return model;
    }

    public int getYear() {
        return year;
    }

    @Override
    public String toString() {
        return "Car{" +
                "brand='" + brand + ''' +
                ", model='" + model + ''' +
                ", year=" + year +
                '}';
    }
}

class SortByBrandThenYear implements Comparator<Car> {
    @Override
    public int compare(Car car1, Car car2) {
        int brandComparison = car1.getBrand().compareTo(car2.getBrand());
        if (brandComparison != 0) {
            return brandComparison;
        } else {
            return car1.getYear() - car2.getYear();
        }
    }
}

public class Main {
    public static void main(String[] args) {
        List<Car> cars = new ArrayList<>();
        cars.add(new Car("BMW", "X5", 2022));
        cars.add(new Car("BMW", "X5", 2019));
        cars.add(new Car("Honda", "Accord", 2022));
        cars.add(new Car("Ford", "Mustang", 2020));

        Collections.sort(cars, new SortByBrandThenYear());

        for (Car car : cars) {
            System.out.println(car);
        }
    }
}

5.3. Explanation

  • The SortByBrandThenYear Comparator first compares the brands of the two cars.
  • If the brands are different, it returns the comparison result.
  • If the brands are the same, it compares the years of the two cars and returns the comparison result.

6. Common Use Cases for Comparators in Java

Comparators are used in a variety of scenarios in Java development. Here are some common use cases:

6.1. Sorting Collections

The most common use case is sorting collections of objects using Collections.sort() or Arrays.sort().

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        List<Integer> numbers = new ArrayList<>();
        numbers.add(5);
        numbers.add(2);
        numbers.add(8);
        numbers.add(1);

        Collections.sort(numbers, (a, b) -> a - b); // Sort in ascending order

        System.out.println(numbers); // Output: [1, 2, 5, 8]
    }
}

6.2. Sorting Custom Objects

Comparators are essential for sorting custom objects based on specific fields or criteria.

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

class Employee {
    private String name;
    private int salary;

    public Employee(String name, int salary) {
        this.name = name;
        this.salary = salary;
    }

    public String getName() {
        return name;
    }

    public int getSalary() {
        return salary;
    }

    @Override
    public String toString() {
        return "Employee{" +
                "name='" + name + ''' +
                ", salary=" + salary +
                '}';
    }
}

public class Main {
    public static void main(String[] args) {
        List<Employee> employees = new ArrayList<>();
        employees.add(new Employee("Alice", 50000));
        employees.add(new Employee("Bob", 60000));
        employees.add(new Employee("Charlie", 55000));

        Collections.sort(employees, (e1, e2) -> e1.getSalary() - e2.getSalary()); // Sort by salary

        for (Employee employee : employees) {
            System.out.println(employee);
        }
    }
}

6.3. Priority Queues

Comparators are used to define the priority of elements in a priority queue.

import java.util.PriorityQueue;

public class Main {
    public static void main(String[] args) {
        PriorityQueue<Integer> pq = new PriorityQueue<>((a, b) -> b - a); // Max heap

        pq.add(5);
        pq.add(2);
        pq.add(8);
        pq.add(1);

        while (!pq.isEmpty()) {
            System.out.println(pq.poll()); // Output: 8, 5, 2, 1
        }
    }
}

6.4. Custom Data Structures

Comparators can be used to implement custom data structures that require specific sorting or comparison logic.

6.5. Sorting with External Libraries

Many external libraries and frameworks use Comparators for sorting and comparison operations.

7. Best Practices for Using Comparators

To effectively use Comparators in Java, consider these best practices:

7.1. Null Safety

Ensure that your Comparator handles null values gracefully to avoid NullPointerException.

import java.util.Comparator;

class SortByYear implements Comparator<Car> {
    @Override
    public int compare(Car car1, Car car2) {
        if (car1 == null && car2 == null) {
            return 0;
        } else if (car1 == null) {
            return -1; // car2 comes first
        } else if (car2 == null) {
            return 1; // car1 comes first
        } else {
            return car1.getYear() - car2.getYear();
        }
    }
}

7.2. Consistency with equals()

Ideally, a Comparator’s comparison logic should be consistent with the equals() method of the class. If compare(a, b) == 0, then a.equals(b) should also be true.

7.3. Use Lambda Expressions for Simple Comparisons

For simple, one-off comparisons, use lambda expressions to reduce boilerplate code and improve readability.

7.4. Avoid Mutable State

Ensure that your Comparator does not rely on mutable state, as this can lead to unpredictable sorting behavior.

7.5. Document Your Comparators

Provide clear and concise documentation for your Comparators, explaining the sorting logic and any specific considerations.

8. Advanced Comparator Techniques

Explore these advanced techniques to enhance your use of Comparators:

8.1. Reverse Ordering

You can easily reverse the ordering of a Comparator using Collections.reverseOrder() or by implementing the reverse logic in the compare() method.

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        List<Integer> numbers = new ArrayList<>();
        numbers.add(5);
        numbers.add(2);
        numbers.add(8);
        numbers.add(1);

        Collections.sort(numbers, Collections.reverseOrder()); // Sort in descending order

        System.out.println(numbers); // Output: [8, 5, 2, 1]
    }
}

8.2. Comparator Chaining

You can chain multiple Comparators together to create a more complex sorting logic. This involves comparing objects based on multiple criteria in a specific order.

import java.util.Comparator;

class SortByBrandThenYear implements Comparator<Car> {
    @Override
    public int compare(Car car1, Car car2) {
        int brandComparison = car1.getBrand().compareTo(car2.getBrand());
        if (brandComparison != 0) {
            return brandComparison;
        } else {
            return car1.getYear() - car2.getYear();
        }
    }
}

8.3. Using Comparator.comparing()

Java 8 introduced the Comparator.comparing() method, which provides a concise way to create Comparators based on a specific field or key.

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

class Car {
    private String brand;
    private String model;
    private int year;

    public Car(String brand, String model, int year) {
        this.brand = brand;
        this.model = model;
        this.year = year;
    }

    public String getBrand() {
        return brand;
    }

    public String getModel() {
        return model;
    }

    public int getYear() {
        return year;
    }

    @Override
    public String toString() {
        return "Car{" +
                "brand='" + brand + ''' +
                ", model='" + model + ''' +
                ", year=" + year +
                '}';
    }
}

public class Main {
    public static void main(String[] args) {
        List<Car> cars = new ArrayList<>();
        cars.add(new Car("BMW", "X5", 2022));
        cars.add(new Car("BMW", "X5", 2019));
        cars.add(new Car("Honda", "Accord", 2022));
        cars.add(new Car("Ford", "Mustang", 2020));

        Collections.sort(cars, Comparator.comparing(Car::getBrand).thenComparing(Car::getYear));

        for (Car car : cars) {
            System.out.println(car);
        }
    }
}

9. Pitfalls to Avoid When Using Comparators

Be aware of these common pitfalls when working with Comparators:

9.1. Inconsistent Comparisons

Ensure that your Comparator provides consistent comparisons. If compare(a, b) > 0, then compare(b, a) should be less than 0. Inconsistent comparisons can lead to incorrect sorting results.

9.2. Reliance on External State

Avoid relying on external state in your Comparator, as this can lead to unpredictable behavior and make your code harder to debug.

9.3. Ignoring Edge Cases

Consider edge cases such as null values, empty strings, and boundary conditions when implementing your Comparator.

9.4. Performance Issues

Be mindful of the performance implications of your Comparator, especially when sorting large collections. Avoid complex or computationally expensive comparisons.

10. Real-World Examples of Comparators

Consider these real-world examples to see how Comparators are used in practice:

10.1. E-Commerce Application

In an e-commerce application, you might use Comparators to sort products by price, rating, or popularity.

10.2. Social Media Platform

In a social media platform, you might use Comparators to sort posts by date, likes, or comments.

10.3. Financial Application

In a financial application, you might use Comparators to sort transactions by date, amount, or type.

10.4. Gaming Application

In a gaming application, you might use Comparators to sort players by score, level, or rank.

11. Comparator Use Cases in Different Sorting Algorithms

Comparators are fundamental in various sorting algorithms, enabling customized sorting logic.

11.1. Collections.sort()

The Collections.sort() method utilizes a Comparator to sort elements in a list according to the defined comparison logic.

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        List<String> names = new ArrayList<>();
        names.add("Charlie");
        names.add("Alice");
        names.add("Bob");

        // Sort the list using a Comparator to sort alphabetically
        Collections.sort(names, (a, b) -> a.compareTo(b));

        System.out.println(names); // Output: [Alice, Bob, Charlie]
    }
}

11.2. Arrays.sort()

Similarly, Arrays.sort() can use a Comparator to sort arrays of objects based on custom criteria.

import java.util.Arrays;
import java.util.Comparator;

public class Main {
    public static void main(String[] args) {
        Integer[] numbers = {5, 2, 8, 1};

        // Sort the array using a Comparator to sort in descending order
        Arrays.sort(numbers, (a, b) -> b - a);

        System.out.println(Arrays.toString(numbers)); // Output: [8, 5, 2, 1]
    }
}

11.3. TreeSet

A TreeSet uses a Comparator to maintain elements in a sorted order.

import java.util.TreeSet;

public class Main {
    public static void main(String[] args) {
        // Create a TreeSet with a Comparator to sort in reverse order
        TreeSet<Integer> sortedNumbers = new TreeSet<>((a, b) -> b - a);
        sortedNumbers.add(5);
        sortedNumbers.add(2);
        sortedNumbers.add(8);
        sortedNumbers.add(1);

        System.out.println(sortedNumbers); // Output: [8, 5, 2, 1]
    }
}

11.4. TreeMap

A TreeMap can also utilize a Comparator to sort its keys based on custom logic.

import java.util.TreeMap;

public class Main {
    public static void main(String[] args) {
        // Create a TreeMap with a Comparator to sort keys in reverse order
        TreeMap<Integer, String> sortedMap = new TreeMap<>((a, b) -> b - a);
        sortedMap.put(5, "Five");
        sortedMap.put(2, "Two");
        sortedMap.put(8, "Eight");
        sortedMap.put(1, "One");

        System.out.println(sortedMap); // Output: {8=Eight, 5=Five, 2=Two, 1=One}
    }
}

12. Working with Different Data Types in Comparators

Comparators can be used with various data types, including primitive types, strings, and custom objects.

12.1. Primitive Types

When working with primitive types, you can directly compare the values using standard comparison operators.

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        List<Integer> numbers = new ArrayList<>();
        numbers.add(5);
        numbers.add(2);
        numbers.add(8);
        numbers.add(1);

        // Sort the list of integers in ascending order
        Collections.sort(numbers, (a, b) -> a - b);

        System.out.println(numbers); // Output: [1, 2, 5, 8]
    }
}

12.2. Strings

For strings, you can use the compareTo() method to compare them lexicographically.

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        List<String> names = new ArrayList<>();
        names.add("Charlie");
        names.add("Alice");
        names.add("Bob");

        // Sort the list of strings in alphabetical order
        Collections.sort(names, (a, b) -> a.compareTo(b));

        System.out.println(names); // Output: [Alice, Bob, Charlie]
    }
}

12.3. Custom Objects

When working with custom objects, you can compare them based on one or more fields, as demonstrated in previous examples with the Car and Employee classes.

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

class Car {
    private String brand;
    private String model;
    private int year;

    public Car(String brand, String model, int year) {
        this.brand = brand;
        this.model = model;
        this.year = year;
    }

    public String getBrand() {
        return brand;
    }

    public String getModel() {
        return model;
    }

    public int getYear() {
        return year;
    }

    @Override
    public String toString() {
        return "Car{" +
                "brand='" + brand + ''' +
                ", model='" + model + ''' +
                ", year=" + year +
                '}';
    }
}

public class Main {
    public static void main(String[] args) {
        List<Car> cars = new ArrayList<>();
        cars.add(new Car("BMW", "X5", 2022));
        cars.add(new Car("BMW", "X5", 2019));
        cars.add(new Car("Honda", "Accord", 2022));
        cars.add(new Car("Ford", "Mustang", 2020));

        // Sort the list of cars by year
        Collections.sort(cars, (car1, car2) -> car1.getYear() - car2.getYear());

        for (Car car : cars) {
            System.out.println(car);
        }
    }
}

13. Creating Reusable Comparators

To promote code reuse, consider creating reusable Comparators that can be used in multiple contexts.

13.1. Static Comparators

Create static Comparator instances that can be accessed and used throughout your application.

import java.util.Comparator;

class Car {
    private String brand;
    private String model;
    private int year;

    public Car(String brand, String model, int year) {
        this.brand = brand;
        this.model = model;
        this.year = year;
    }

    public String getBrand() {
        return brand;
    }

    public String getModel() {
        return model;
    }

    public int getYear() {
        return year;
    }

    @Override
    public String toString() {
        return "Car{" +
                "brand='" + brand + ''' +
                ", model='" + model + ''' +
                ", year=" + year +
                '}';
    }

    // Static Comparator for sorting by year
    public static final Comparator<Car> SORT_BY_YEAR = (car1, car2) -> car1.getYear() - car2.getYear();

    // Static Comparator for sorting by brand
    public static final Comparator<Car> SORT_BY_BRAND = (car1, car2) -> car1.getBrand().compareTo(car2.getBrand());
}

13.2. Generic Comparators

Create generic Comparators that can work with different types of objects.

import java.util.Comparator;

class GenericComparator<T> implements Comparator<T> {
    private final Comparator<T> comparator;

    public GenericComparator(Comparator<T> comparator) {
        this.comparator = comparator;
    }

    @Override
    public int compare(T obj1, T obj2) {
        return comparator.compare(obj1, obj2);
    }
}

13.3. Using Enums for Comparators

Enums can be used to define a set of Comparators, each representing a different sorting strategy.

import java.util.Comparator;

enum CarSortStrategy {
    BY_YEAR((car1, car2) -> car1.getYear() - car2.getYear()),
    BY_BRAND((car1, car2) -> car1.getBrand().compareTo(car2.getBrand()));

    private final Comparator<Car> comparator;

    CarSortStrategy(Comparator<Car> comparator) {
        this.comparator = comparator;
    }

    public Comparator<Car> getComparator() {
        return comparator;
    }
}

14. Performance Considerations When Using Comparators

While Comparators offer flexibility, it’s crucial to consider their performance impact, especially when dealing with large datasets.

14.1. Minimize Complexity

Keep the comparison logic in your Comparator as simple and efficient as possible. Avoid complex computations or I/O operations within the compare() method.

14.2. Avoid String Comparisons

String comparisons can be relatively expensive. If possible, cache the results of string comparisons or use a more efficient comparison method.

14.3. Use Primitive Comparisons

Primitive type comparisons are generally faster than object comparisons. If possible, use primitive types instead of objects in your comparison logic.

14.4. Benchmark Your Comparators

Benchmark your Comparators with representative datasets to identify any performance bottlenecks. Use profiling tools to analyze the performance of your comparison logic.

15. Java 8 Comparator API Enhancements

Java 8 introduced several enhancements to the Comparator API, making it easier to create and use Comparators.

15.1. Comparator.comparing()

The Comparator.comparing() method provides a concise way to create Comparators based on a specific field or key.

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

class Car {
    private String brand;
    private String model;
    private int year;

    public Car(String brand, String model, int year) {
        this.brand = brand;
        this.model = model;
        this.year = year;
    }

    public String getBrand() {
        return brand;
    }

    public String getModel() {
        return model;
    }

    public int getYear() {
        return year;
    }

    @Override
    public String toString() {
        return "Car{" +
                "brand='" + brand + ''' +
                ", model='" + model + ''' +
                ", year=" + year +
                '}';
    }
}

public class Main {
    public static void main(String[] args) {
        List<Car> cars = new ArrayList<>();
        cars.add(new Car("BMW", "X5", 2022));
        cars.add(new Car("BMW", "X5", 2019));
        cars.add(new Car("Honda", "Accord", 2022));
        cars.add(new Car("Ford", "Mustang", 2020));

        // Sort the list of cars by brand using Comparator.comparing()
        Collections.sort(cars, Comparator.comparing(Car::getBrand));

        for (Car car : cars) {
            System.out.println(car);
        }
    }
}

15.2. Comparator.thenComparing()

The Comparator.thenComparing() method allows you to chain multiple Comparators together to create a more complex sorting logic.


import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

class Car {
    private String brand;
    private String model;
    private int year;

    public Car(String brand, String model, int year) {
        this.brand = brand;
        this.model = model;
        this.year = year;
    }

    public String getBrand() {
        return brand;
    }

    public String getModel() {
        return model;
    }

    public int getYear() {
        return year;
    }

    @Override
    public String toString() {
        return "Car{" +
                "brand='" + brand + ''' +
                ", model='" + model + ''' +
                ", year=" + year +
                '}';
    }
}

public class Main {
    public static void main(String[] args) {
        List<Car> cars = new ArrayList<>();
        cars.add(new Car("BMW", "X5", 2022));
        cars.add(new Car("BMW", "X5", 2019));
        cars.add(new Car("Honda", "Accord", 2022));
        cars.add(new Car("Ford", "Mustang", 2020));

        // Sort the list of cars by brand, then by year using Comparator.then

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 *