Trial book

Задание порядка в множестве ( natural ordering )

Разберемся с вопросом задания порядка на некотором множестве объектов.

Определение порядка на множестве не такой простой вопрос, если это понятие нужно поддерживать в программе. Обычно он решается путем задания функции сравнения. Т.е. для элементов какого-то множества задается функция, которая позволяет сравнить два элемента этого множества. В качестве результата такая функция возвращает целое число, которое меньше нуля, если первый элемент меньше второго, ноль, если они равны, и больше нуля, если первый элемент больше второго. Иными словами, для задания порядка нам нужно запрограммировать некоторую функцию, возвращающую логическую разность двух объектов множества.

Однако даже при таком подходе остается масса вариантов реализации данного принципа. В Java эта проблема решена стандартными средствами библиотеки языка, а именно — путем задания интерфейсов, используемых при задании порядка. При этом, Java позволяет сравнивать объекты как одного, так и разных классов.

Для задания порядка используются следующие интерфейсы: Comparable и Comparator. Они дают два различных способа задания порядка. Мы рассмотрим оба этих интерфейса, определим их назначение, разберем, как ими пользоваться и чем они отличаются друг от друга.

Интерфейс Comparable предназначен для определения так называемого естественного порядка ( natural ordering ). Этот интерфейс определен в пакете java.lang. Обратившись к документации мы увидим, что данный интерфейс содержит всего один метод.

public int compareTo(Object o)

Сравнивает объект с другим объектом.

Пример:

public class A implements Comparable {

      String name;

  public int compareTo(Object obj) {
      return name.compareTo(((A)obj).name);
  }
  . . .
}

Интерфейс Comparator

Определен в пакете java.util. Работа с использованием Comparator отличается от того, что мы рассмотрели по интерфейсу Comparable. Здесь строится отдельный вспомогательный класс (будем называть его компаратор), используемый для сравнения объектов.

Обратимся к документации. Интерфейс Comparator имеет два метода

public int compare(Object o1, Object o2)
public boolean equals(Object obj)

Второй из методов используется редко — он предназначен для сравнения самих компараторов. Более того, реализовывать данный метод необязательно.

Пример:

public class Employer {    // служащий
     int tabnom;        // табельный номер
     String name;      // ФИО
     static NameComparator nameComparator = new  NameComparator();
     static TabComparator tabComparator = new  TabComparator();

     public static Comparator getNameComparator() {
           return nameComparator;
     }

     public static Comparator getTabComparator() {
           return tabComparator;
     }

     static class NameComparator implements Comparator {

          public int compare(Object o1, Object o2) {
                return ((Employer)o1).name.compareTo(((Employer)o2).name);
          }
// метод equals() реализовывать не обязательно
     }

     static class TabComparator  implements Comparator {
          public int compare(Object o1, Object o2) {
                return ((Employer)o1).tabnom —  ((Employer)o2).tabnom;
          }
     }
   . . .
}

Вопрос 1.

В чем разница между интерфейсами Comparator и Comparable?

Вопрос 2.

В каких случаях следует реализовывать интерфейсы Comparator и Comparable при создании новых классов?