2011-05-14 20 views
6

Me he encontrado con un problema interesante del cual estoy bastante seguro es culpa de HashMap. Consideremos el siguiente código de depuración (AMAP es un HashMap, clave es un valor pasado a este método)HashMap dice que Key no existe aunque lo hace

System.out.println("getBValues - Given: " + key); 
System.out.println("getBValues - Contains Key: " + AMap.containsKey(key)); 
System.out.println("getBValues - Value: " + AMap.get(key)); 
for(Map.Entry<A,HashSet<B>> entry : AMap.entrySet()) { 
    System.out.println("getBValues(key) - Equal: " + (key.equals(entry.getKey()))); 
    System.out.println("getBValues(key) - HashCode Equal: "+(key.hashCode() == entry.getKey().hashCode())); 
    System.out.println("getBValues(key) - Key: " + entry.getKey()); 
    System.out.println("getBValues(key) - Value: " + entry.getValue()); 
} 

Ahora, en este mapa inserto una sola tecla (Canal) y el valor. Más tarde tratar de obtener el valor de nuevo con get() y ejecutar este código de depuración que en mi caso da este resultado:

getBValues - Given: Channel(...) 
getBValues - Contains Key: false <--- Doesnt contain key?! 
getBValues - Value: null <--- Null (bad) 
getBValues(key) - Equal: true <--- Given key and AMap key is equal 
getBValues(key) - HashCode Equal: true 
getBValues(key) - Key: Channel(Same...) 
getBValues(key) - Value: [] <--- Not null (This is the expected result) 

Como se puede ver, ir a buscar la llave del HashMap directamente no funciona, pero bucle a través de lo Obtenga la misma clave exacta, lo que significa que simplemente no se puede encontrar con get(). Mi pregunta es ¿qué causaría esto? ¿Cómo puede get() no encontrar una clave que existe?

Proporcionaré un ejemplo de código de esto, pero parece que no puedo reproducir esto de forma independiente.

¿Alguna sugerencia sobre qué podría estar causando esto?

+3

* "... de lo cual estoy bastante seguro es culpa de HashMap" *. Repite después de mi. "El error está en ** mi ** código". - http://programmers.stackexchange.com/questions/1785/what-should-every-programmer-know-about-programming/1842#1842 –

+0

@Stephen Lo estaba diciendo más como "Alguna 'característica' en HashMap está causando esto " – TheLQ

Respuesta

4

Por lo que puedo ver, todavía no han descartado si tiene que ver con inmutabilidad. Si lo hace:

aMap.put(key, value); 
key.setFieldIncludedInHashCodeAndEquals(25); 

entonces se obtendría el resultado de lo alto.

Para descartar esta posibilidad, ya sea nos muestran más de su código o, en el bucle en el ejemplo anterior, agregue

System.out.println(aMap.get(entry.getKey())); 

Asimismo, el uso de un depurador. De esta forma, puedes ver si tu objeto está en el cubo correcto.

+0

Hmm ... eso me dio un valor nulo. Supongo que hashCode está cambiando después de haber sido agregado. Veré si puedo actualizar mi código a algo funcional. – TheLQ

+0

Entonces, ¿algún campo, siendo parte de hashCode o igual en el objeto que almacenaste como clave en aMap, cambia después de que agregaste el objeto a tu mapa? – Buhb

+0

Es por esto que las claves en los mapas deben ser inmutables. – duffymo

8

Apuesto a que no anuló equals y hashCode correctamente en su clase de clave de canal. Eso lo explicaría.

Joshua Bloch le indica cómo hacerlo correctamente en su capítulo "Effective Java" 3.

http://java.sun.com/developer/Books/effectivejava/Chapter3.pdf

+0

lo hice con el Proyecto Lombok, incluso excluyendo específicamente 2 HashSets en la clase que afectaría la igualdad. – TheLQ

+0

No sé qué es el Proyecto Lombok; No puedo decir si eso significa "sí, tengo un equals apropiado y hashCode implementado". Mejor si las llaves son inmutables también. ¿Es eso cierto para tu canal? – duffymo

+1

En su prueba particular hashCode da el mismo valor para la clave y la clave almacenada. Puede implementarse incorrectamente o correctamente, pero esta instancia lo tiene correcto. key.equals (entry.key) también da verdadero. la única causa restante que puedo ver si entry.key.equals (key) es falso. –

Cuestiones relacionadas