instead - mapping en java
Bucle infinito cuando se usa una tecla varias veces en HashMap (5)
HashMap
cae en un ciclo infinito.
No puedo entender por qué HashMap
arroja un error de stackoverflow cuando se usa la misma clave varias veces.
Código:
import java.util.HashMap;
public class Test {
public static void main(String[] args) {
HashMap hm = new HashMap();
hm.put(hm, "1");
hm.put(hm, "2");
}
}
Error:
Excepción en el hilo "principal" java.lang.StackOverflowError
El problema no es que el mapa hash haga explotar la pila para la "misma clave" ingresada dos veces, sino debido a su elección particular de la clave del mapa. Está agregando el mapa hash a sí mismo.
Para explicar mejor, parte del contrato de Map es que las claves no deben cambiar de forma que afecte a sus métodos equals (o hashCode para ese caso).
Cuando agregaste un mapa a sí mismo como una clave, cambiaste la clave (mapa) de una manera que hace que devuelva un hashCode diferente de cuando primero agregaste el mapa.
Para obtener más información, esto es de la base JDK para la interfaz de Mapa:
Nota: se debe tener mucho cuidado si los objetos mutables se utilizan como claves de mapa. El comportamiento de un mapa no se especifica si el valor de un objeto se cambia de una manera que afecta a las comparaciones iguales mientras el objeto es una clave en el mapa. Un caso especial de esta prohibición es que no está permitido que un mapa se contenga como una clave. Si bien es permisible que un mapa se contenga a sí mismo como un valor, se recomienda extrema precaución: los métodos equal y hashCode ya no están bien definidos en dicho mapa.
Para ubicar una clave en el HashMap
(que se realiza cada vez que llamas a put
o get
o containsKey
), se hashCode
método hashCode
para la clave.
Para HashMap
, hashCode()
es una función de hashCode()
de todas las entradas del Map
, y hashCode
cada entrada es una función de hashCode
s de la clave y el valor. Como su clave es la misma instancia de HashMap
, al calcular el hashCode
de esa clave se produce una recursión infinita de las hashCode
método hashCode
, lo que lleva a Error
.
Usar una HashMap
como clave para HashMap
es una mala idea.
Utiliza como clave el hashmap en sí mismo -> eso significa recursión -> sin condición de salida -> .
Simplemente use una tecla (Long, String, Object, cualquier otra cosa que desee).
Y sí, como sugiere Seek Addo, agregue tipos con <> corchetes.
No es posible agregarlo a un Map
como una clave. De javadoc :
Un caso especial de esta prohibición es que no está permitido que un mapa se contenga como una clave .
El problema es que está utilizando como clave no un objeto estándar (cualquier objeto con métodos equals
y hashCode
bien definidos, que no es el mapa en sí), sino el mapa en sí.
El problema está en cómo se hashCode
el hashCode
de HashMap
:
public int hashCode() {
int h = 0;
Iterator<Entry<K,V>> i = entrySet().iterator();
while (i.hasNext())
h += i.next().hashCode();
return h;
}
Como puede ver, para calcular el hashCode del mapa, itera sobre todos los elementos del mapa. Y para cada elemento, calcula el hashCode. Como el único elemento del mapa tiene como clave el mapa en sí, se convierte en una fuente de recursión.
Reemplazar el mapa con otro objeto que pueda usarse como clave (con equals
bien definidos y hashCode
) funcionará:
import java.util.HashMap;
public class Test {
public static void main(String[] args) {
HashMap hm = new HashMap();
String key = "k1";
hm.put(key, "1");
hm.put(key, "2");
}
}
Está utilizando el mismo nombre de objeto como clave para que sea un bucle infinito.
entonces es un desbordamiento de pila