¿Por qué se Comparable
usa Java ? ¿Por qué alguien implementaría Comparable
en una clase? ¿Cuál es un ejemplo de la vida real en el que necesita implementar comparables?
¿Por qué se Comparable
usa Java ? ¿Por qué alguien implementaría Comparable
en una clase? ¿Cuál es un ejemplo de la vida real en el que necesita implementar comparables?
Respuestas:
Aquí hay una muestra de la vida real. Tenga en cuenta que String
también se implementa 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;
}
}
luego..
/**
* 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
?
Comparable define un ordenamiento natural. Lo que esto significa es que lo está definiendo cuando un objeto debe considerarse "menor que" o "mayor que".
Supongamos que tiene un montón de enteros y desea ordenarlos. Eso es bastante fácil, solo póngalos en una colección ordenada, ¿verdad?
TreeSet<Integer> m = new TreeSet<Integer>();
m.add(1);
m.add(3);
m.add(2);
for (Integer i : m)
... // values will be sorted
Pero ahora supongamos que tengo algún objeto personalizado, donde la ordenación tiene sentido para mí, pero no está definida. Digamos que tengo datos que representan distritos por código postal con densidad de población, y quiero ordenarlos por densidad:
public class District {
String zipcode;
Double populationDensity;
}
Ahora, la forma más fácil de ordenarlos es definirlos con un orden natural mediante la implementación de Comparable, lo que significa que hay una forma estándar de definir estos objetos para que se ordenen:
public class District implements Comparable<District>{
String zipcode;
Double populationDensity;
public int compareTo(District other)
{
return populationDensity.compareTo(other.populationDensity);
}
}
Tenga en cuenta que puede hacer lo equivalente definiendo un comparador. La diferencia es que el comparador define la lógica de ordenamiento fuera del objeto . Quizás en un proceso separado necesito ordenar los mismos objetos por código postal; en ese caso, el orden no es necesariamente una propiedad del objeto, o difiere del orden natural de los objetos. Puede usar un comparador externo para definir un orden personalizado en enteros, por ejemplo, ordenándolos por su valor alfabético.
Básicamente, la lógica de ordenamiento tiene que existir en alguna parte. Eso puede ser -
en el objeto en sí, si es naturalmente comparable (extiende enteros -eg enteros)
suministrado en un comparador externo, como en el ejemplo anterior.
TreeSet<Integer>
lugar de TreeMap<Integer>
, ya que este último no existe, los TreeMaps siempre son <Key,Value>
pares. Por cierto, un hipotético TreeMap<District, Object>
solo funcionaría si el Distrito implementara Comparable, ¿verdad? Todavía trato de entender esto
Citado del javadoc;
Esta interfaz impone un orden total en los objetos de cada clase que lo implementa. Este orden se conoce como el orden natural de la clase, y el método compareTo de la clase se conoce como su método de comparación natural.
Las listas (y matrices) de objetos que implementan esta interfaz se pueden ordenar automáticamente por Collections.sort (y Arrays.sort). Los objetos que implementan esta interfaz se pueden usar como claves en un mapa ordenado o como elementos en un conjunto ordenado, sin la necesidad de especificar un comparador.
Editar: ... e hizo que la parte importante fuera audaz.
El hecho de que una clase se implemente Comparable
significa que puede tomar dos objetos de esa clase y compararlos. Algunas clases, como ciertas colecciones (función de clasificación en una colección) que mantienen los objetos en orden, se basan en que sean comparables (para clasificar, necesita saber qué objeto es el "más grande", etc.).
La mayoría de los ejemplos anteriores muestran cómo reutilizar un objeto comparable existente en la función compareTo. Si desea implementar su propio compareTo cuando quiera comparar dos objetos de la misma clase, diga un objeto AirlineTicket que le gustaría ordenar por precio (menos se clasifica primero), seguido por el número de escala (nuevamente, menos es clasificado primero), haría lo siguiente:
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;
}
}
Una manera fácil de implementar comparaciones de múltiples campos es con la comparación de Guava's Cadena , entonces puede decir
public int compareTo(Foo that) {
return ComparisonChain.start()
.compare(lastName, that.lastName)
.compare(firstName, that.firstName)
.compare(zipCode, that.zipCode)
.result();
}
en vez 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 ejemplo, cuando desea tener una colección o mapa ordenado
Comparable se utiliza para comparar instancias de su clase. Podemos comparar instancias de muchas maneras, por eso necesitamos implementar un método compareTo
para saber cómo (atributos) queremos comparar instancias.
Dog
clase: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
clase: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
*/
}
}
Aquí hay un buen ejemplo de cómo usar comparable en Java:
http://www.onjava.com/pub/a/onjava/2003/03/12/java_comp.html?page=2
Cuando implementa la Comparable
interfaz, necesita implementar el método compareTo()
. Lo necesita para comparar objetos, para utilizar, por ejemplo, el método de clasificación de la ArrayList
clase. Necesita una forma de comparar sus objetos para poder ordenarlos. Por lo tanto, necesita un compareTo()
método personalizado en su clase para poder usarlo con el ArrayList
método de clasificación. El compareTo()
método devuelve -1,0,1.
Acabo de leer un capítulo correspondiente en Java Head 2.0, todavía estoy aprendiendo.
Bien, pero ¿por qué no solo definir un compareTo()
método sin implementar una interfaz comparable? Por ejemplo, una clase City
definida por su name
y temperature
y
public int compareTo(City theOther)
{
if (this.temperature < theOther.temperature)
return -1;
else if (this.temperature > theOther.temperature)
return 1;
else
return 0;
}