Почему класс Java должен быть сопоставимым?

Почему используется Java Comparable? Почему кто-то реализует Comparable в классе? Что такое пример реальной жизни, когда вам нужно сопоставлять?

Ответ 1

Вот пример реальной жизни. Обратите внимание, что String также реализует Comparable.

class Author implements Comparable<Author>{
    String firstName;
    String lastName;

    @Override
    public int compareTo(Author other){
        // compareTo should return < 0 if this is supposed to be
        // less than other, > 0 if this is supposed to be greater than 
        // other and 0 if they are supposed to be equal
        int last = this.lastName.compareTo(other.lastName);
        return last == 0 ? this.firstName.compareTo(other.firstName) : last;
    }
}

позже..

/**
 * List the authors. Sort them by name so it will look good.
 */
public List<Author> listAuthors(){
    List<Author> authors = readAuthorsFromFileOrSomething();
    Collections.sort(authors);
    return authors;
}

/**
 * List unique authors. Sort them by name so it will look good.
 */
public SortedSet<Author> listUniqueAuthors(){
    List<Author> authors = readAuthorsFromFileOrSomething();
    return new TreeSet<Author>(authors);
}

Ответ 2

Сопоставимый определяет естественный порядок. Это означает, что вы определяете его, когда один объект следует считать "меньше" или "больше".

Предположим, что у вас есть куча целых чисел, и вы хотите их отсортировать. Это довольно легко, просто поместите их в отсортированную коллекцию, не так ли?

TreeSet<Integer> m = new TreeSet<Integer>(); 
m.add(1);
m.add(3);
m.add(2);
for (Integer i : m)
... // values will be sorted

Но теперь предположим, что у меня есть какой-то пользовательский объект, где сортировка имеет смысл для меня, но есть undefined. Скажем, у меня есть данные, представляющие районы по zipcode с плотностью населения, и я хочу сортировать их по плотности:

public class District {
  String zipcode; 
  Double populationDensity;
}

Теперь самый простой способ их сортировки - определить их с помощью естественного упорядочения путем реализации Comparable, что означает стандартный способ определения этих объектов:

public class District implements Comparable<District>{
  String zipcode; 
  Double populationDensity;
  public int compareTo(District other)
  {
    return populationDensity.compareTo(other.populationDensity);
  }
}

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

В принципе логика порядка должна существовать где-то. Это может быть -

  • в самом объекте, если он естественно сопоставим (расширяет сравнимые целые числа)

  • поставляемый во внешнем компараторе, как в приведенном выше примере.

Ответ 3

Цитируется из javadoc;

Этот интерфейс накладывает общий упорядочение объектов каждого класса который ее реализует. Это упорядочение называемый классом естественным упорядочение и класс compareTo метод называется его естественным метод сравнения.

Списки (и массивы) объектов, которые реализовать этот интерфейс можно сортировать автоматически через Collections.sort(и Arrays.sort). Объекты, которые реализуют этот интерфейс можно использовать в качестве ключей в сортированная карта или элементы в сортированный набор, без необходимости укажите компаратор.

Изменить:.. и сделал важный бит жирным.

Ответ 4

Тот факт, что класс реализует Comparable, означает, что вы можете взять два объекта из этого класса и сравнить их. Некоторые классы, такие как определенные коллекции (функция сортировки в коллекции), которые хранят объекты в порядке, полагаются на их сопоставимость (для сортировки вам нужно знать, какой объект является "самым большим" и т.д.).

Ответ 5

В большинстве приведенных выше примеров показано, как повторно использовать существующий сопоставимый объект в функции compareTo. Если вы хотите реализовать свой собственный compareTo, когда вы хотите сравнить два объекта одного и того же класса, скажем, объект AirlineTicket, который вы хотите отсортировать по цене (меньше занимает первое место), а затем число остановок (опять же, меньше занимает первое место), вы бы сделали следующее:

class AirlineTicket implements Comparable<Cost>
{
    public double cost;
    public int stopovers;
    public AirlineTicket(double cost, int stopovers)
    {
        this.cost = cost; this.stopovers = stopovers ;
    }

    public int compareTo(Cost o)
    {
        if(this.cost != o.cost)
          return Double.compare(this.cost, o.cost); //sorting in ascending order. 
        if(this.stopovers != o.stopovers)
          return this.stopovers - o.stopovers; //again, ascending but swap the two if you want descending
        return 0;            
    }
}

Ответ 6

Простым способом реализации нескольких полевых сравнений является Guava ComparisonChain - тогда вы можете сказать

   public int compareTo(Foo that) {
     return ComparisonChain.start()
         .compare(lastName, that.lastName)
         .compare(firstName, that.firstName)
         .compare(zipCode, that.zipCode)
         .result();
   }

вместо

  public int compareTo(Person other) {
    int cmp = lastName.compareTo(other.lastName);
    if (cmp != 0) {
      return cmp;
    }
    cmp = firstName.compareTo(other.firstName);
    if (cmp != 0) {
      return cmp;
    }
    return Integer.compare(zipCode, other.zipCode);
  }
}

Ответ 7

Например, если вы хотите иметь отсортированную коллекцию или map

Ответ 8

Сравнение используется для сравнения экземпляров вашего класса. Мы можем сравнивать экземпляры по многим причинам, поэтому нам нужно реализовать метод compareTo, чтобы узнать, как (атрибуты) мы хотим сравнивать экземпляры.

Dog класс:

package test;
import java.util.Arrays;

public class Main {

    public static void main(String[] args) {
        Dog d1 = new Dog("brutus");
        Dog d2 = new Dog("medor");
        Dog d3 = new Dog("ara");
        Dog[] dogs = new Dog[3];
        dogs[0] = d1;
        dogs[1] = d2;
        dogs[2] = d3;

        for (int i = 0; i < 3; i++) {
            System.out.println(dogs[i].getName());
        }
        /**
         * Output:
         * brutus
         * medor
         * ara
         */

        Arrays.sort(dogs, Dog.NameComparator);
        for (int i = 0; i < 3; i++) {
            System.out.println(dogs[i].getName());
        }
        /**
         * Output:
         * ara
         * medor
         * brutus
         */

    }
}

Main класс:

package test;

import java.util.Arrays;

public class Main {

    public static void main(String[] args) {
        Dog d1 = new Dog("brutus");
        Dog d2 = new Dog("medor");
        Dog d3 = new Dog("ara");
        Dog[] dogs = new Dog[3];
        dogs[0] = d1;
        dogs[1] = d2;
        dogs[2] = d3;

        for (int i = 0; i < 3; i++) {
            System.out.println(dogs[i].getName());
        }
        /**
         * Output:
         * brutus
         * medor
         * ara
         */

        Arrays.sort(dogs, Dog.NameComparator);
        for (int i = 0; i < 3; i++) {
            System.out.println(dogs[i].getName());
        }
        /**
         * Output:
         * ara
         * medor
         * brutus
         */

    }
}

Вот хороший пример использования сопоставимых в Java:

http://www.onjava.com/pub/a/onjava/2003/03/12/java_comp.html?page=2

Ответ 9

Когда вы реализуете интерфейс Comparable, вам необходимо реализовать метод compareTo. Это нужно для сравнения объектов, чтобы использовать, например, метод сортировки класса ArrayList. Вам нужен способ сравнить ваши объекты, чтобы их сортировать. Таким образом, вам нужен собственный метод compareTo в вашем классе, чтобы вы могли использовать его с методом сортировки ArrayList. Метод compareTo возвращает -1,0,1.

Я только что прочитал соответствующую главу в Java Head 2.0, которую я все еще изучаю.

Ответ 10

ОК, но почему бы просто не определить метод compareTo без реализации сопоставимого интерфейса. Например, класс City определяется его именем и температурой и

public int compareTo(City theOther)
    {
        if (this.temperature<theOther.temperature) return -1;
        else if (this.temperature>theOther.temperature) return 1;
        else return 0;
    }