2008-12-04 6 views
7

Sabía usted que:¿Por qué AbstractCollection no implementa equals()?

Map<Object,Object> m1 = new HashMap<Object, Object>(); 
Map<Object,Object> m2 = new HashMap<Object, Object>(); 
System.out.println("m1.equals(m2) = "+m1.equals(m2)); 
System.out.println("m1.keySet().equals(m2.keySet()) = " 
      +m1.keySet().equals(m2.keySet())); 
System.out.println("m1.entrySet().equals(m2.entrySet()) = " 
      +m1.entrySet().equals(m2.entrySet())); 
System.out.println("m1.values().equals(m2.values()) = " 
      +m1.values().equals(m2.values())); 

habría de salida:

m1.equals(m2) = true 
m1.keySet().equals(m2.keySet()) = true 
m1.entrySet().equals(m2.entrySet()) = true 
m1.values().equals(m2.values()) = false 

Esto es causado por el hecho de que AbstractCollection (que hereda de HashMap$Values) no anula #equals().

¿Tiene alguna idea de por qué es así?

Respuesta

6

Según el contrato de Collection#equals(), no hay métodos de igual a igual para() Collection s, y por lo tanto AbstractCollection no pueden proporcionar uno.

Tenga en cuenta que HashMap$Values no es ni un conjunto ni una lista, por lo tanto el dilema y en cierto sentido la razón por la que no es compatible con equals().

+0

Me gusta tu respuesta, has dicho algo similar a mí, pero de una mejor manera. Los valores no son un conjunto o una lista, pero se puede pensar como una bolsa. ¿Por qué no implementar equals() con semántica de bolsa? –

+0

@Motlin: Acepto que nuestras respuestas son similares, lamentablemente respondimos unos segundos después.En cuanto a la semántica de bolsa, un conmutativo contiene la prueba All() desafortunadamente rompería los contratos de List.equals() y Set.equals() (ya que ellos mismos ya no serían conmutativos). –

0

No estoy seguro de si esa es la razón oficial, pero AbstractCollection evita agregar restricciones semánticas a posibles subclases. La semántica de la igualdad está determinada por la naturaleza de la estructura de datos de herencia concreta, y en particular en función de si su estructura está ordenada y si permite duplicados.

Por ejemplo, considere TreeSet, LinkedList, bolsa, etc.

Por cierto, en relación con el código que envió, lo que es el tipo real de lo que es devuelto por los valores? Eso debería ser una subclase con una implementación concreta. Si su mapa está vacío cuando ejecuta este código, es posible que termine con algo que no considere que dos conjuntos vacíos sean iguales.

+0

La pregunta menciona el tipo devuelto por los valores() es HashMap $ Valores –

+0

Correcto, pero ¿qué es? ¿Es una estructura de datos personalizada o una estructura de datos existente? ¿Supongo que es una especie de iterador? – Uri

4

AbstractList y AbstractSet extienden AbstractCollection, y tienen diferentes comportamientos para sus métodos equals(), especificados por las interfaces List y Set. La interfaz para Collection dice:

Mientras que la interfaz Collection no añade estipulaciones del contrato general para los Object.equals, los programadores que implementan la interfaz Collection "directamente" (en otras palabras, crear un clase que es una Colección pero no es un Conjunto o una Lista) debe tener cuidado si eligen anular el Object.equals.

So AbstractCollection definitivamente no debe anular equals(). Dicho esto, realmente no sé por qué HashMap $ Values ​​no implementaría equals() en sí mismo.

+0

Gran respuesta. Quizás formule otra pregunta más específicamente sobre por qué HashMap $ Values ​​no implementa equals() (probablemente porque nadie lo necesita). Creo que voy a validar la respuesta de Greg Case ya que parece preferir su redacción. – Michel

Cuestiones relacionadas