¿Por qué debería una clase Java implementar comparable?
136
¿Por qué se Comparableusa Java ? ¿Por qué alguien implementaría Comparableen una clase? ¿Cuál es un ejemplo de la vida real en el que necesita implementar comparables?
Aquí hay una muestra de la vida real. Tenga en cuenta que Stringtambién se implementa Comparable.
classAuthorimplementsComparable<Author>{String firstName;String lastName;@Overridepublicint 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 equalint 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.
*/publicList<Author> listAuthors(){List<Author> authors = readAuthorsFromFileOrSomething();Collections.sort(authors);return authors;}/**
* List unique authors. Sort them by name so it will look good.
*/publicSortedSet<Author> listUniqueAuthors(){List<Author> authors = readAuthorsFromFileOrSomething();returnnewTreeSet<Author>(authors);}
Solo quiero señalar que a menudo querrá anular equals(y, por lo tanto hashCode) para ser coherente con su compareTométodo. Por ejemplo, esto es necesario si quieres que la clase juegue bien con a TreeSet.
pidge
¿Por qué no simplemente regresar last?
Anirban Nag 'tintinmj'
@ AnirbanNag'tintinmj 'para ordenar automáticamente por el nombre en caso de que el apellido sea el mismo.
OddDev
Más uno por la buena explicación de por qué compareTo devuelve un int y lo que significa. Más útil.
james.garriss
1
@ user3932000: Correcto, ese es prácticamente el punto de todas las interfaces. ¡Pero tenga en cuenta que "otros métodos Java" incluye métodos escritos por el usuario! De hecho, diría que el código del usuario consume la mayoría de las interfaces. En bases de código más grandes, "usted mismo" se convierte rápidamente en "otros"
Enno Shioji
40
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 =newTreeSet<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:
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:
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.
buen ejemplo, pero tiene que ser en 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
phil294
14
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.
Yo diría que la oración después de la que has marcado es igual de importante (si no más).
Michael Borgwardt
8
El hecho de que una clase se implemente Comparablesignifica 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:
classAirlineTicketimplementsComparable<Cost>{publicdouble cost;publicint stopovers;publicAirlineTicket(double cost,int stopovers){this.cost = cost;this.stopovers = stopovers ;}publicint compareTo(Cost o){if(this.cost != o.cost)returnDouble.compare(this.cost, o.cost);//sorting in ascending order. if(this.stopovers != o.stopovers)returnthis.stopovers - o.stopovers;//again, ascending but swap the two if you want descendingreturn0;}}
Lo que quiere decir Fernando es: si almacena "cosas" que implementan Comparable en una clase de contenedor ordenado, la clase de contenedor ordenado puede ordenar automáticamente esas "cosas".
Ian Durkan
2
Comparable se utiliza para comparar instancias de su clase. Podemos comparar instancias de muchas maneras, por eso necesitamos implementar un método compareTopara saber cómo (atributos) queremos comparar instancias.
Dog clase:
package test;import java.util.Arrays;publicclassMain{publicstaticvoid main(String[] args){Dog d1 =newDog("brutus");Dog d2 =newDog("medor");Dog d3 =newDog("ara");Dog[] dogs =newDog[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;publicclassMain{publicstaticvoid main(String[] args){Dog d1 =newDog("brutus");Dog d2 =newDog("medor");Dog d3 =newDog("ara");Dog[] dogs =newDog[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:
Cuando implementa la Comparableinterfaz, necesita implementar el método compareTo(). Lo necesita para comparar objetos, para utilizar, por ejemplo, el método de clasificación de la ArrayListclase. 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 ArrayListmé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 Citydefinida por su namey temperaturey
Respuestas:
Aquí hay una muestra de la vida real. Tenga en cuenta que
String
también se implementaComparable
.luego..
fuente
equals
(y, por lo tantohashCode
) para ser coherente con sucompareTo
método. Por ejemplo, esto es necesario si quieres que la clase juegue bien con aTreeSet
.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?
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:
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:
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.
fuente
TreeSet<Integer>
lugar deTreeMap<Integer>
, ya que este último no existe, los TreeMaps siempre son<Key,Value>
pares. Por cierto, un hipotéticoTreeMap<District, Object>
solo funcionaría si el Distrito implementara Comparable, ¿verdad? Todavía trato de entender estoCitado del javadoc;
Editar: ... e hizo que la parte importante fuera audaz.
fuente
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.).fuente
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:
fuente
Una manera fácil de implementar comparaciones de múltiples campos es con la comparación de Guava's Cadena , entonces puede decir
en vez de
fuente
Por ejemplo, cuando desea tener una colección o mapa ordenado
fuente
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:Main
clase: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
fuente
Cuando implementa la
Comparable
interfaz, necesita implementar el métodocompareTo()
. Lo necesita para comparar objetos, para utilizar, por ejemplo, el método de clasificación de laArrayList
clase. Necesita una forma de comparar sus objetos para poder ordenarlos. Por lo tanto, necesita uncompareTo()
método personalizado en su clase para poder usarlo con elArrayList
método de clasificación. ElcompareTo()
método devuelve -1,0,1.Acabo de leer un capítulo correspondiente en Java Head 2.0, todavía estoy aprendiendo.
fuente
Bien, pero ¿por qué no solo definir un
compareTo()
método sin implementar una interfaz comparable? Por ejemplo, una claseCity
definida por suname
ytemperature
yfuente