Por que uma class Java deve ser comparada?

Por que o Java Comparable usado? Por que alguém implementaria o Comparable em uma class? O que é um exemplo da vida real em que você precisa implementar comparável?

Aqui está uma amostra da vida real. Observe que o String também implementa o Comparable .

 class Author implements Comparable{ 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; } } 

mais tarde..

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

Comparável define uma ordenação natural. O que isto significa é que você está definindo quando um object deve ser considerado “menor que” ou “maior que”.

Suponha que você tenha muitos inteiros e queira classificá-los. Isso é muito fácil, basta colocá-los em uma coleção ordenada, certo?

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

Mas agora suponha que eu tenha algum object personalizado, onde a ordenação faz sentido para mim, mas é indefinida. Digamos que eu tenha dados representando distritos por código postal com densidade populacional e quero classificá-los por densidade:

 public class District { String zipcode; Double populationDensity; } 

Agora, a maneira mais fácil de classificá-los é defini-los com um ordenamento natural, implementando o Comparable, o que significa que há uma maneira padrão pela qual esses objects são definidos para serem ordenados:

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

Note que você pode fazer o equivalente definindo um comparador. A diferença é que o comparador define a lógica de ordenação fora do object . Talvez em um processo separado eu precise ordenar os mesmos objects por CEP – nesse caso, a ordenação não é necessariamente uma propriedade do object, ou difere da ordenação natural dos objects. Você poderia usar um comparador externo para definir uma ordem personalizada em números inteiros, por exemplo, classificando-os por seu valor alfabético.

Basicamente, a lógica de ordenação deve existir em algum lugar. Isso pode ser –

  • no próprio object, se é naturalmente comparável (estende-se Comparable -eg integers)

  • fornecido em um comparador externo, como no exemplo acima.

Citado do javadoc;

Essa interface impõe uma ordenação total nos objects de cada class que a implementa. Essa ordenação é chamada de ordenação natural da class e o método compareTo da class é chamado de método de comparação natural.

Listas (e matrizes) de objects que implementam essa interface podem ser classificadas automaticamente por Collections.sort (e Arrays.sort). Objetos que implementam essa interface podem ser usados ​​como chaves em um mapa ordenado ou como elementos em um conjunto classificado, sem a necessidade de especificar um comparador.

Edit: ..e fez o importante bit em negrito.

O fato de que uma class implementa Comparable significa que você pode pegar dois objects dessa class e compará-los. Algumas classs, como certas collections (function de sorting em uma coleção) que mantêm os objects em ordem, dependem de serem comparáveis ​​(para classificar você precisa saber qual object é o “maior” e assim por diante).

A maioria dos exemplos acima mostra como reutilizar um object comparável existente na function compareTo. Se você quiser implementar sua própria compareTo quando quiser comparar dois objects da mesma class, digamos um object AirlineTicket que você gostaria de classificar por preço (menos é classificado primeiro), seguido por número de escala (novamente, menos é em primeiro lugar), você faria o seguinte:

 class AirlineTicket implements Comparable { 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; } } 

Uma maneira fácil de implementar múltiplas comparações de campo é com o ComparisonChain da Guava – então você pode dizer

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

ao invés de

  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); } } 

Por exemplo, quando você deseja ter uma coleção ou um mapa ordenado

Comparável é usado para comparar instâncias de sua class. Podemos comparar instâncias de muitas maneiras, e é por isso que precisamos implementar um método compareTo para saber como (atributos) queremos comparar instâncias.

Classe do 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 */ } } 

Classe 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 */ } } 

Aqui está um bom exemplo de como usar comparáveis ​​em Java:

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

Quando você implementa a interface Comparable , você precisa implementar o método compareTo() . Você precisa comparar objects, para usar, por exemplo, o método de sorting da class ArrayList . Você precisa de uma maneira de comparar seus objects para poder classificá-los. Então, você precisa de um método customizado compareTo() em sua class para poder usá-lo com o método de ordenação ArrayList . O método compareTo() retorna -1,0,1.

Acabei de ler um capítulo de acordo no Java Head 2.0, ainda estou aprendendo.

OK, mas por que não apenas definir um método compareTo() sem implementar interface comparável. Por exemplo, uma class City definida por seu name e temperature e

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