Для чого Comparable
використовується Java ? Чому хтось реалізовує Comparable
в класі? Який приклад із реального життя, де потрібно реалізувати порівнянне?
Для чого Comparable
використовується Java ? Чому хтось реалізовує Comparable
в класі? Який приклад із реального життя, де потрібно реалізувати порівнянне?
Відповіді:
Ось зразок реального життя. Зверніть увагу, що 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);
}
last
?
Порівняльне визначає природне впорядкування. Це означає, що ви визначаєте це, коли один об'єкт слід вважати "меншим" або "більшим за".
Припустимо, у вас є купа цілих чисел, і ви хочете їх сортувати. Це досить просто, просто покладіть їх у відсортовану колекцію, правда?
TreeSet<Integer> m = new TreeSet<Integer>();
m.add(1);
m.add(3);
m.add(2);
for (Integer i : m)
... // values will be sorted
Але тепер припустимо, що у мене є якийсь спеціальний об'єкт, де сортування має для мене сенс, але не визначене. Скажімо, у мене є дані, що представляють райони за поштовим індексом з щільністю населення, і я хочу їх сортувати за щільністю:
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);
}
}
Зауважте, що ви можете зробити рівнозначну річ, визначивши компаратор. Різниця полягає в тому, що компаратор визначає логіку впорядкування поза об'єктом . Можливо, в окремому процесі мені потрібно замовити ті самі об'єкти за поштовим індексом - в такому випадку впорядкування не обов'язково є властивістю об'єкта або відрізняється від природного впорядкування об'єктів. Ви можете використовувати зовнішній компаратор для визначення замовного замовлення на цілі числа, наприклад, сортуючи їх за алфавітним значенням.
В основному логіка впорядкування повинна десь існувати. Це може бути -
в самому об'єкті, якщо він природно порівнянний (розширює Порівняльні -eg цілі числа)
поставляється у зовнішньому компараторі, як у наведеному вище прикладі.
TreeSet<Integer>
замість цього TreeMap<Integer>
, оскільки останній не існує, TreeMaps - це завжди <Key,Value>
-пари. Доречно, гіпотетична TreeMap<District, Object>
спрацювала б лише в тому випадку, якщо Район реалізує Порівняльне, правда? Ще намагаюся зрозуміти це
Цитується з javadoc;
Цей інтерфейс накладає загальне впорядкування на об'єкти кожного класу, який його реалізує. Це впорядкування називається природним впорядкуванням класу, а метод порівняння класу - природним методом порівняння.
Списки (та масиви) об'єктів, що реалізують цей інтерфейс, можна автоматично сортувати за Collections.sort (та Arrays.sort). Об'єкти, що реалізують цей інтерфейс, можуть використовуватися як ключі в відсортованій карті або як елементи в відсортованому наборі без необхідності вказувати компаратор.
Редагувати: .. і зробив важливий трохи сміливим.
Те, що клас реалізує, Comparable
означає, що ви можете взяти два об’єкти з цього класу та порівняти їх. Деякі класи, як-от певні колекції (функція сортування в колекції), які зберігають об'єкти, щоб покладатися на їх порівнянність (для сортування потрібно знати, який об’єкт є "найбільшим" тощо).
Більшість прикладів, наведених вище, показують, як повторно використовувати існуючий порівняний об'єкт у функції 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;
}
}
Простий спосіб здійснити декілька порівнянь поля - це Guava's ComparingChain - тоді ви можете сказати
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);
}
}
Порівняльний використовується для порівняння примірників вашого класу. Ми можемо порівняти екземпляри багатьма способами, тому нам потрібно реалізувати метод 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
Коли ви реалізуєте Comparable
інтерфейс, вам потрібно реалізувати метод compareTo()
. Він вам потрібен для порівняння об'єктів, щоб використовувати, наприклад, метод сортування ArrayList
класу. Вам потрібен спосіб порівняння ваших об'єктів, щоб мати можливість їх сортувати. Отже, вам потрібен спеціальний compareTo()
метод у вашому класі, щоб ви могли використовувати його з ArrayList
методом сортування. ThecompareTo()
метод повертає -1,0,1.
Я щойно прочитав відповідний розділ у Java Head 2.0, я все ще вчуся.
Гаразд, але чому б просто не визначити compareTo()
метод без реалізації порівнянного інтерфейсу. Наприклад клас, City
визначений його name
та temperature
та
public int compareTo(City theOther)
{
if (this.temperature < theOther.temperature)
return -1;
else if (this.temperature > theOther.temperature)
return 1;
else
return 0;
}