2009-04-27 8 views
7

Quiero hacer una clase utilizable en SortedSet | SortedMap.¿Tiene sentido que equals y compareTo sean inconsistentes?

class MyClass implements Comparable<MyClass>{ 
    // the only thing relevant to comparisons: 
    private final String name; 

    //... 
} 

Las instancias de la clase 'se deben ordenar por su propiedad de nombre.
Sin embargo, no deseo que las instancias igualmente nombradas se consideren iguales.

Así que un contenido SortedSet se vería como a, a, a, b, c.
(Normalmente, SortedSet sólo permitiría a, b, c)

En primer lugar: ¿es esto (filosóficamente) consistente?

Si es así, ¿tengo que esperar un comportamiento impredecible, cuando no anulación equals(...) y hashCode()?

Editar:
Lo siento, mi pregunta parece inconsistente:
quiero poner múltiples valores "igual" dentro de un conjunto , que no permite este por concepto.
Entonces, por favor no responda mi pregunta más.
Gracias a todos los que ya respondieron.

+0

¿Por qué no utilizar un tipo de colección diferente? –

+0

Sí, google-collection-API's MultiSet | MultiMap parece bueno para esto. Espero tanto que el Sun, aehm, Oracle chicos algún día agreguen funcionalidad a la colección API de Java ... –

Respuesta

18

Déjame hacerte una pregunta: ¿tiene sentido tener a.compareTo(b) devolver 0 y a.equals(b) devolver false?

Yo usaría un Comparator<MyClass> en su lugar. Esta es la razón por la cual todas las implementaciones de SortedMap/SortedSet que conozco le permiten pasar en un Comparator en la creación.

+0

Me inclinaría a responder: no tiene sentido;) Gracias, olvidé que hay algo así como un Comparador;) –

+0

Pregunta correcta. – Joshua

2

Effective Java recomienda que si no se implementa compareTo consistente con equals deberá indicar claramente para:

El idioma recomendado es "Nota: Esta clase tiene un orden natural que es incompatible con los iguales. "

0

Sólo hay que poner este código en el método es igual y no te ocurra pensar en ello de nuevo:

public boolean equals(Object obj) { 
    if (this == obj) return true; 
    if (!(obj instanceof MyClass)) return false; 
    return 0 == this.compareTo((MyClass) obj); 
} 
+0

Pero si implementa equals(), también debe implementar hashcode(). De lo contrario, pueden suceder cosas extrañas. –

+0

Puede delegar hashCode a alguna otra propiedad o un método que devuelva un valor int comparable. Pero no te molestes, ya que hashCode es como comprobar si es la misma referencia, no si tienen el mismo valor. – Azder

4

Desde el Javadoc para Comparable

Es muy recomendable (aunque no requerido) que los ordenamientos naturales sean consistentes con iguales.Esto es así porque los conjuntos ordenados (y ordenados mapas) sin comparadores explícitas comportan "extrañamente" cuando se utilizan con elementos (o teclas) cuyos ordenamiento natural es incompatible con iguales

Si quiere tener CompareTo inconsistente con equals(), se recomienda que utilice un comparador explícito al proporcionar una clase que implementa Comparator.

Si es así, ¿debo esperar un comportamiento impredecible, cuando no anulo equals (...) y hashcode()?

Aún debe reemplazar equals() y hashcode(). Si o no iguales() y hashcode() son consistentes con compareTo es una cuestión diferente.

Cuestiones relacionadas