Cuándo usar Comparable y Comparador

Tengo una lista de objetos que necesito ordenar en un campo, digamos Puntaje. Sin pensarlo mucho, escribí una nueva clase que implementa Comparator, que hace la tarea y funciona.

Ahora, mirando hacia atrás en esto, me pregunto si debería haber hecho que mi clase implemente Comparable en lugar de crear una nueva clase que implemente Comparator. El puntaje es el único campo sobre el que se ordenarán los objetos.

  1. Lo que he hecho aceptable como práctica?

  2. Es el enfoque correcto “Primero, la clase debe implementar Comparable (para el ordenamiento natural) y si se requiere una comparación de campo alternativa, entonces cree una nueva clase que implemente el Comparador”?

  3. Si (2) arriba es verdadero, ¿significa que uno debe implementar el Comparador solo después de que la clase implemente la opción Comparable? (Suponiendo que tengo la clase original).

Yo diría que un objeto debería implementar Comparable si esa es la forma natural clara de clasificar la clase, y cualquiera debería ordenar la clase, por lo general querría hacerlo de esa manera.

Sin embargo, si la clasificación fue un uso inusual de la clase, o la clasificación solo tiene sentido para un caso de uso específico, entonces un Comparador es una mejor opción.

Dicho de otra manera, dado el nombre de la clase, ¿está claro cómo clasificaría una persona comparable, o tiene que recurrir a leer el javadoc? Si es el último, las probabilidades son que cada caso de uso de clasificación futura requiera un comparador, en cuyo punto la implementación de comparable puede ralentizar a los usuarios de la clase, no acelerarlos.

Use Comparable si desea definir un comportamiento de ordenamiento predeterminado (natural) del objeto en cuestión, una práctica común es usar un identificador técnico o natural (¿de la base de datos?) Del objeto para esto.

Utilice Comparator si desea definir un comportamiento de ordenamiento externo controlable , esto puede anular el comportamiento de ordenamiento predeterminado.

Use Comparable :

  • si el objeto está bajo tu control
  • si el comportamiento de comparación es el comportamiento principal de comparación.

Usar Comparator :

  • si el objeto está fuera de su control y no puede hacer que implementen Comparable .
  • cuando desee comparar comportamientos diferentes del comportamiento predeterminado (que se especifica en Comparable ).

Comparablejava.lang.Comparable: int compareTo(Object o1)

Un objeto comparable es capaz de compararse con otro objeto. La clase en sí debe implementar la interfaz java.lang.Comparable para poder comparar sus instancias.

  • Capaz de comparar el objeto actual con el objeto proporcionado.
  • Al usar esto, podemos implementar only one sort sequence basada en las propiedades de las instancias. EX: Person.id
  • Algunas de las clases predefinidas como String, Wrapper classes, Date, Calendar han implementado una interfaz comparable.

Comparadorjava.util.Comparator: int compare(Object o1, Object o2)

Un objeto de comparación es capaz de comparar dos objetos diferentes. La clase no compara sus instancias, sino algunas instancias de otras clases. Esta clase de comparador debe implementar la interfaz java.util.Comparator.

  • Capaz de comparar dos objetos del mismo tipo.
  • Al usar esto podemos implementar many sort sequence y nombrar cada una de ellas, según las propiedades de las instancias. EX: Person.id, Person.name, Person.age
  • Podemos implementar la interfaz del Comparador en nuestras clases predefinidas para la clasificación personalizada.

Ejemplo:

 public class Employee implements Comparable { private int id; private String name; private int age; private long salary; // Many sort sequences can be created with different names. public static Comparator NameComparator = new Comparator() { @Override public int compare(Employee e1, Employee e2) { return e1.getName().compareTo(e2.getName()); } }; public static Comparator idComparator = new Comparator() { @Override public int compare(Employee e1, Employee e2) { return Integer.valueOf(e1.getId()).compareTo(Integer.valueOf(e2.getId())); } }; public Employee() { } public Employee(int id, String name, int age, long salary){ this.id = id; this.name = name; this.age = age; this.salary = salary; } // setters and getters. // Only one sort sequence can be created with in the class. @Override public int compareTo(Employee e) { //return Integer.valueOf(this.id).compareTo(Integer.valueOf(e.id)); //return Character.toString(this.name.charAt(0)).compareToIgnoreCase(Character.toString(e.name.charAt(0))); if (this.id > e.id) { return 1; }else if(this.id < e.id){ return -1; }else { return Character.toString(this.name.charAt(0)).compareToIgnoreCase(Character.toString(e.name.charAt(0))); } } public static void main(String[] args) { Employee e1 = new Employee(5, "Yash", 22, 1000); Employee e2 = new Employee(8, "Tharun", 24, 25000); List list = new ArrayList(); list.add(e1); list.add(e2); Collections.sort(list); // call @compareTo(o1) Collections.sort(list, Employee.nameComparator); // call @compare (o1,o2) Collections.sort(list, Employee.idComparator); // call @compare (o1,o2) } } 
  • Para la clasificación personalizada, optamos por el comparador @compare (o1, o2) para otros escenarios en los que comparamos @compareTo (o1), sin cambiar el código si queremos ordenar más de un campo, entonces usamos el comparador.

Para Java 8 Lambda: comparador consulte mi publicación.

Comparable debe usarse cuando compara instancias de la misma clase.

El comparador se puede usar para comparar instancias de diferentes clases.

Comparable se implementa por clase, que necesita definir un orden natural para sus objetos. Al igual que String implementa Comparable.

En caso de que uno quiera un orden de clasificación diferente, entonces puede implementar el comparador y definir su propia forma de comparar dos instancias.

Comparator hace todo lo que hace comparable, más más.

| | Comparable | Comparator ._______________________________________________________________________________ Is used to allow Collections.sort to work | yes | yes Can compare multiple fields | yes | yes Lives inside the class you're comparing and serves | | as a “default” way to compare | yes | yes Can live outside the class you're comparing | no | yes Can have multiple instances with different method names | no | yes Input arguments can be a list of | just Object| Any type Can use enums | no | yes

Encontré el mejor enfoque para usar comparadores como clases anónimas de la siguiente manera:

 private static void sortAccountsByPriority(List accounts) { Collections.sort(accounts, new Comparator() { @Override public int compare(AccountRecord a1, AccountRecord a2) { return a1.getRank().compareTo(a2.getRank()); } }); } 

Puede crear múltiples versiones de dichos métodos directamente dentro de la clase que planea ordenar. Entonces puedes tener:

  • sortAccountsByPriority
  • sortAccountsByType
  • sortAccountsByPriorityAndType

    etc …

Ahora puede usar estos métodos de clasificación en cualquier lugar y obtener la reutilización del código. Esto me da todo lo que un comparable haría, más más … así que no veo ninguna razón para usar comparable en absoluto.

Yo diría:

  • si la comparación es intuitiva, entonces, por supuesto, implementar Comparable
  • si no está claro si su comparación es intuitiva, use un Comparador ya que es más explícito y, por lo tanto, más claro para la pobre alma que tiene que mantener el código.
  • si hay más de una comparación intuitiva posible, preferiría un Comparador, posiblemente comstackdo por un método de fábrica en la clase para comparar.
  • si la comparación es de propósito especial, use el Comparador
  • Si en el momento de escribir la clase solo tienes un caso de uso de clasificación, utiliza Comparable.
  • Solo cuando tiene más de una estrategia de clasificación implementa un Comparador.

Los siguientes puntos lo ayudan a decidir en qué situaciones se debe usar Comparable y en qué Comparador:

1) Disponibilidad del código

2) Criterios de selección únicos versus múltiples

3) Arays.sort () y Collection.sort ()

4) Como claves en SortedMap y SortedSet

5) Más Número de clases Versus flexibilidad

6) Comparaciones interclase

7) orden natural

Para obtener un artículo más detallado, puede consultar cuándo utilizarlo de forma comparable y cuándo usar el comparador.

Hubo una pregunta similar aquí: ¿ Cuándo debería una clase ser Comparable y / o Comparador?

Diría lo siguiente: Implementar Comparable para algo así como un ordenamiento natural, por ejemplo, basado en una identificación interna

Implemente un Comparador si tiene un algoritmo de comparación más complejo, por ejemplo, campos múltiples, etc.

Si necesita clasificación de orden natural – Comparable con el usuario SI necesita clasificación de pedidos personalizados – Utilice comparador

Ejemplo:

 Class Employee{ private int id; private String name; private String department; } 

La ordenación de orden natural se basaría en la identificación porque sería única y la orden personalizada sortin g sería el nombre y el departamento.

Refrences:
¿Cuándo debería una clase ser Comparable y / o Comparador? http://javarevisited.blogspot.com/2011/06/comparator-and-comparable-in-java.html

Comparable:
Cuando queremos almacenar solo elementos homogéneos y se requiere un orden de clasificación natural por defecto, podemos ir a la clase implementando comparable interfaz comparable .

Comparador:
Siempre que deseemos almacenar elementos homogéneos y heterogéneos y queremos ordenar por orden de clasificación personalizado por defecto, podemos optar por comparator interfaz de comparator .

Si la ordenación de objetos debe basarse en el orden natural, utilice Comparable, mientras que si la ordenación debe realizarse en atributos de diferentes objetos, utilice Comparator en Java.

Diferencia principal entre Comparable y Comparador:

 +------------------------------------------------------------------------------------+ ¦ Comparable ¦ Comparator ¦ ¦-----------------------------------------+------------------------------------------¦ ¦ java.lang.Comparable ¦ java.util.Comparator ¦ ¦-----------------------------------------+------------------------------------------¦ ¦ int objOne.compareTo(objTwo) ¦ int compareTo(objOne, objTwo) ¦ ¦-----------------------------------------+------------------------------------------¦ ¦ Negative, if objOne < objTwo ¦ Same as Comparable ¦ ¦ Zero, if objOne == objTwo ¦ ¦ ¦ Positive, if objOne > objTwo ¦ ¦ ¦-----------------------------------------+------------------------------------------¦ ¦ You must modify the clas whose ¦ You build a class separate from to sort. ¦ ¦ instances you want to sort. ¦ the class whose instances you want ¦ ¦-----------------------------------------+------------------------------------------¦ ¦ Only one sort sequemce can be created ¦ Many sort sequences can be created ¦ ¦-----------------------------------------+------------------------------------------¦ ¦ Implemented frequently in the API by: ¦ Meant to be implemented to sort ¦ ¦ String, Wrapper classes, Date, Calandar ¦ instances of third-party classes. ¦ +------------------------------------------------------------------------------------+ 

Un enfoque muy simple es suponer que la clase de entidad en cuestión esté representada en la base de datos y luego en la tabla de la base de datos ¿necesitaría un índice compuesto por campos de clase de entidad? Si la respuesta es sí, impleméntela de manera comparable y use los campos de índice para el orden de clasificación natural. En todos los demás casos use el comparador.

Mi necesidad estaba basada en la fecha.

Entonces, usé Comparable y funcionó fácilmente para mí.

 public int compareTo(GoogleCalendarBean o) { // TODO Auto-generated method stub return eventdate.compareTo(o.getEventdate()); } 

Una restricción con Comparable es que no se pueden usar para colecciones distintas de List.

Si posees la clase, mejor ve con Comparable . En general, Comparator se usa si usted no posee la clase, pero debe usarla TreeSet o TreeMap porque el Comparador se puede pasar como un parámetro en el contructor de TreeSet o TreeMap. Puede ver cómo usar Comparador y Comparable en http://preciselyconcise.com/java/collections/g_comparator.php

Me han pedido ordenar un rango definido de números en un tiempo mejor que nlogn en una entrevista. (No usa el tipo de conteo)

La implementación de la interfaz Comparable sobre un objeto permite que los algos de ordenación implícitos usen el método contrarrestado compareTo para ordenar los elementos de clasificación y que sea el tiempo lineal.

  • Comparador para muchos criterios de comparación
  • Comparable cuando tienes solo un criterio.

Mi anotación lib para implementar Comparable y Comparator :

 public class Person implements Comparable { private String firstName; private String lastName; private int age; private char gentle; @Override @CompaProperties({ @CompaProperty(property = "lastName"), @CompaProperty(property = "age", order = Order.DSC) }) public int compareTo(Person person) { return Compamatic.doComparasion(this, person); } } 

Haga clic en el enlace para ver más ejemplos. http://code.google.com/p/compamatic/wiki/CompamaticByExamples