Si implemento un comparador personalizado, ¿se considera una buena práctica anular equals
además de compare
?
Además, ¿existe un contrato definido para Comparator
?Mejor práctica del comparador
Respuesta
El contrato de Comparador se define in its javadoc. En particular:
Se debe tener precaución cuando se utiliza un comparador capaz de imponer un ordenamiento incompatible con iguales para ordenar un conjunto ordenado (o mapa ordenados). Supongamos que un conjunto ordenado (o un mapa ordenado) con un comparador explícito c se usa con elementos (o claves) extraídos de un conjunto S. Si el ordenamiento impuesto por c sobre S es inconsistente con los iguales, el conjunto ordenado (o el mapa ordenado) comportarse "extrañamente". En particular, el conjunto ordenado (o el mapa ordenado) violará el contrato general para el conjunto (o mapa), que se define en términos de iguales.
Por lo general, si 2 objetos son iguales desde el punto de vista equals
pero no desde un punto de vista compareTo
, puede almacenar tanto los objetos como claves en un TreeMap. Esto puede conducir a un comportamiento no intuitivo. También se puede hacer a propósito en situaciones específicas.
Por ejemplo, this answer muestra un ejemplo donde es deseable que sea igual y compare Para ser inconsistente.
Los javadoc for Comparator estados:
El orden impuesto por un comparador c en un conjunto de elementos de S se dice que es consistente con los iguales si y sólo si c.compare (e1, e2) == 0 tiene el mismo valor booleano que e1.equals (e2) para cada e1 y e2 en S.
Se debe tener precaución al usar un comparador capaz de imponer un orden incoherente con iguales para ordenar un conjunto ordenado (o un mapa ordenado). Supongamos que un conjunto ordenado (o un mapa ordenado) con un comparador explícito c se usa con elementos (o claves) extraídos de un conjunto S. Si el ordenamiento impuesto por c sobre S es inconsistente con los iguales, el conjunto ordenado (o el mapa ordenado) comportarse "extrañamente". En particular, el conjunto ordenado (o el mapa ordenado) violará el contrato general para el conjunto (o mapa), que se define en términos de iguales.
Entonces la respuesta sería sí, es una buena práctica (al menos para su primera pregunta).
Creo que solo tiene que anular iguales si siente que está probando la igualdad. A menudo, cuando escribo comparadores, comparan propiedades dentro de un objeto y continúo usando compareTo en estas propiedades.
Por ejemplo
public class ToCompare {
public static final Comparator<ToCompare> ID_COMPARATOR = new Comparator(){
@Override
public int compare(ToCompare o1, ToCompare o2) {
return o1.id.compareTo(o2.id);
}
}
private Integer id;
//... other fields here
}
tiendo a almacenar estos comparadores en el objeto como campos static final públicas para que sean accesibles desde cualquier código que lo desea, puede ordenar este objeto. Si el objeto se actualiza (campos agregados/eliminados) entonces puedo ver de inmediato si hay problemas con el comparador en lugar de revisar todos mis problemas de búsqueda de códigos.
Sí. como se sugiere en el documento de Java de Comparator , diría que dependerá de sus necesidades.
Por ejemplo, supongamos que se añade dos elementos a y b tales que (a.equals (b) & & c.compare (a, b)! = 0) a un TreeSet vacío con comparador c. La segunda operación de adición devolverá verdadera (y el tamaño del conjunto de árboles aumentará) porque a y b no son equivalentes desde la perspectiva del conjunto de árboles, aunque esto sea contrario a la especificación del método Set.add.
Pero si se considera el ejemplo de abajo, donde solo tiene que ordenar una lista en particular, es posible que no sea necesario.
Tomemos un ejemplo de la clase Employee
que tiene dos propiedades id
, name
.
class Employee {
int id;// sample so access not considered
String name;// sample so access not considered
}
Supongamos que hay dos opciones separadas a la lista de id
o name
separado tipo. Para lograr esto, necesitaría implementar dos comparadores uno que se compare en id
y otro en el nombre compares
.
Ahora bien, si desea implementar comparador basado en id
como su tipo es tan int
tipo de envoltorio es Integer
y como Integer
proporciona compareTo
método sólo lo utilizan.
Igual es el caso de String
. De esta forma, no tendrá que preocuparse por escribir el método compare
o compareTo
.
No necesito pensar mientras escribo el método compare
ya que siempre uso métodos integrados en las propiedades de los objetos.
class EmpIdComparator implements Comparator<Employee> {
@Override
public int compare(Employee o1, Employee o2) {
return Integer.valueOf(o1.id).compareTo(o2.id);// Make use of
// existing
// comparators
// provided by java
}
}
class EmpNameComparator implements Comparator<Employee> {
@Override
public int compare(Employee o1, Employee o2) {
return o1.name == null ? o2.name == null ? 0 : 1 : o1.name
.compareTo(o2.name);// Make use of
// existing
// comparators
// provided by java
}
}
siento que las otras respuestas pierden el punto: Comparator
's-compare método compara los dos parámetros dados, mientras que un Comparator
' s es igual método compara el Comparator
sí con otro objeto.
el Javadoc para Comparator#equals
de al menos más nuevo JDK explica en detalle:
/**
* Indicates whether some other object is "equal to" this
* comparator. This method must obey the general contract of
* {@link Object#equals(Object)}. Additionally, this method can return
* <tt>true</tt> <i>only</i> if the specified object is also a comparator
* and it imposes the same ordering as this comparator. Thus,
* <code>comp1.equals(comp2)</code> implies that <tt>sgn(comp1.compare(o1,
* o2))==sgn(comp2.compare(o1, o2))</tt> for every object reference
* <tt>o1</tt> and <tt>o2</tt>.<p>
*
* Note that it is <i>always</i> safe <i>not</i> to override
* <tt>Object.equals(Object)</tt>. However, overriding this method may,
* in some cases, improve performance by allowing programs to determine
* that two distinct comparators impose the same order.
*
* @param obj the reference object with which to compare.
* @return <code>true</code> only if the specified object is also
* a comparator and it imposes the same ordering as this
* comparator.
* @see Object#equals(Object)
* @see Object#hashCode()
*/
boolean equals(Object obj);
Como tal, es rara vez útil para anular el iguales-método de Comparator
. Comparable
sería diferente, sin embargo.
- 1. Métodos anidados, mejor práctica
- 2. cmake mejor práctica
- 3. WCF: manejo de errores del lado del servidor. mejor práctica
- 4. Release Management: mejor práctica
- 5. Mejor práctica de clase
- 6. Diseño de SVN: mejor práctica
- 7. Mejor práctica de acoplamiento suelto OSGi
- 8. tipo groovy con la sintaxis del comparador
- 9. Uso del comparador para ordenar ArrayList Java
- 10. Mejor práctica para usar las propiedades del sistema Java
- 11. ¿La mejor práctica para informar errores del cliente con window.onerror?
- 12. C# complejidad del inicializador de objetos. mejor práctica
- 13. Mejor práctica: Organizar pruebas unitarias
- 14. referencia o devolución: mejor práctica
- 15. Java JSON serialization: mejor práctica
- 16. JavaScript y Eventos - Mejor Práctica
- 17. kwargs mejor práctica de análisis
- 18. Mejor práctica: prueba vs rescate
- 19. Mejor práctica para NSUserDefaults sincronizar
- 20. WSDL - sin entrada - mejor práctica
- 21. Mejor práctica de dependencia circular
- 22. Java Comparador
- 23. Java TreeMap (comparador) y obtienes el método ignorando el comparador
- 24. uso del método equals() en la interfaz del comparador?
- 25. ASP.NET: mejor práctica para redirigir a https
- 26. SQL SUBSTRING vs RIGHT - Mejor práctica
- 27. mejor práctica para RESTO booleano resultados
- 28. Mejor práctica para la funcionalidad 'me gusta'
- 29. Mejor práctica: Secuencias de comandos cruzadas legítimas
- 30. APP Mejor Práctica: Estático de búsqueda Entidades
Un error común es mutar un campo usado en hashCode, equals o compareTo. Los haría finales e inmutables cuando sea posible. –
¿Quiere decir 'Comparable'? (O 'compare'?) –
@ TomHawtin-tachado: OP – Jim