Интерфейсы Comparable и Comparator

Существует два способа сравнения объектов:

  • С помощью интерфейса Comparable.
  • С помощью интерфейса Comparator.

1. Интерфейс Comparable

Начнем с интерфейса Comparable

Для того чтобы объекты можно было сравнить и сортировать, они должны реализовать параметризованный интерфейс Comparable.

Интерфейс Comparable содержит один единственный метод int compareTo(T item), который сравнивает текущий объект с объектом, переданным в качестве параметра.

Если этот метод возвращает отрицательное число, то текущий объект будет располагаться перед тем, который передается через параметр. Если метод вернет положительное число, то, наоборот, после второго объекта. Если метод возвращает ноль, значит, оба объекта равны.

Рассмотрим пример реализации интерфейса Comparable:

public class Person implements Comparable<Person> {
    private String firstName;
    private String lastName;
    private int age;

    public Person(String firstName, String lastName, int age) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.age = age;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public int compareTo(Person anotherPerson) {
        int anotherPersonAge = anotherPerson.getAge();
        return this.age - anotherPersonAge;
    }

    @Override
    public String toString() {
        return "Person{" +
                "firstName='" + firstName + '\'' +
                ", lastName='" + lastName + '\'' +
                ", age=" + age +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Person person = (Person) o;

        if (getAge() != person.getAge()) return false;
        if (getFirstName() != null ? !getFirstName().equals(person.getFirstName()) : person.getFirstName() != null)
            return false;
        return getLastName() != null ? getLastName().equals(person.getLastName()) : person.getLastName() == null;

    }

    @Override
    public int hashCode() {
        int result = getFirstName() != null ? getFirstName().hashCode() : 0;
        result = 31 * result + (getLastName() != null ? getLastName().hashCode() : 0);
        result = 31 * result + getAge();
        return result;
    }
}
public class ComparePersonDemo {
    public static void main(String[] args) {
        SortedSet<Person> set = new TreeSet<>();
        set.add(new Person("Саша", "Иванов", 36));
        set.add(new Person("Маша", "Петрова", 23));
        set.add(new Person("Даша", "Сидорова", 34));
        set.add(new Person("Вася", "Иванов", 25));
        set.forEach(System.out::println);
    }
}

2. Интерфейс Comparator

Если класс по какой-то причине не может реализовать интерфейс Comparable, или же просто нужен другой вариант сравнения, используется интерфейс Comparator.

Интерфейс содержит метод int compare(T o1, T o2), который должен быть реализован классом, реализующим компаратор.

Метод compare возвращает числовое значение - если оно отрицательное, то объект o1 предшествует объекту o2, иначе - наоборот. А если метод возвращает ноль, то объекты равны.

Для применения интерфейса нам вначале надо создать класс компаратора, который реализует этот параметризованный интерфейс.

Рассмотрим пример использования интерфейса Comparator:

import java.util.Comparator;

public class PersonComparator implements Comparator<Person> {
     @Override
     public int compare(Person o1, Person o2) {
         return o1.getLastName().compareTo(o2.getLastName());
     }
}
import java.util.SortedSet;
import java.util.TreeSet;

public class PersonComparatorDemo {
    public static void main(String[] args) {
        PersonComparator personComparator = new PersonComparator();
        SortedSet<Person> set = new TreeSet<>(personComparator);
        set.add(new Person("Саша", "Иванов", 36));
        set.add(new Person("Маша", "Петрова", 23));
        set.add(new Person("Даша", "Сидорова", 34));
        set.add(new Person("Вася", "Иванов", 25));
        //Обратите внимание - было добавлено 4 элемента, но распечатано 3
        set.forEach(System.out::println);
    }
}

То же самое перепишем с использованием метода comparing() интерфейса Comparator:

import java.util.Comparator;
import java.util.SortedSet;
import java.util.TreeSet;

public class PersonComparingDemo {
    public static void main(String[] args) {
        Comparator<Person> personComparator =
                Comparator.comparing(Person::getLastName).thenComparing(Person::getAge);
        SortedSet<Person> set = new TreeSet<>(personComparator);
        set.add(new Person("Саша", "Иванов", 36));
        set.add(new Person("Маша", "Петрова", 23));
        set.add(new Person("Даша", "Сидорова", 34));
        set.add(new Person("Вася", "Иванов", 25));
        set.forEach(System.out::println);
    }
}
Read also:
Trustpilot
Trustpilot
Comments