get
en put
HashMap?”. Aquí intentaré explicar la funcionalidad interna usando un ejemplo simple. Sin entrar en demasiada teoría, comenzaremos con un ejemplo para que puedas comprender mejor y luego ver cómo funcionan los métodos get
también put
en Java . Tomemos un ejemplo muy simple. Tenemos una clase Country
(“país” en inglés), usaremos el objeto de clase Country
como clave y el nombre de la capital de este país como valor. A continuación se muestra un ejemplo que nos ayudará a comprender cómo se almacenará un par clave-valor en un mapa hash.
1. País.java
package org.arpit.javapostsforlearning;
public class Country {
String name;
long population;
public Country(String name, long population) {
super();
this.name = name;
this.population = population;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public long getPopulation() {
return population;
}
public void setPopulation(long population) {
this.population = population;
}
// если длина имени в un objetoе Country - четное число,
// то возвращаем 31(любое случайное число), а если нечетное - 95 (любое случайное число).
// указанный ниже метод - это не самый лучший способ генерации хеш-códigoа,
// но мы воспользуемся им для более четкого понимания хеш-карт.
@Override
public int hashCode() {
if(this.name.length()%2==0)
return 31;
else
return 95;
}
@Override
public boolean equals(Object obj) {
Country other = (Country) obj;
if (name.equalsIgnoreCase((other.name)))
return true;
return false;
}
}
Si quieres entender y aprender más sobre métodos hashcode
e iguales, puedes seguir este enlace .
2. HashMapStructure.java (clase principal)
import java.util.HashMap;
import java.util.Iterator;
public class HashMapStructure {
/**
* @author Arpit Mandliya
*/
public static void main(String[] args) {
Country india=new Country("India",1000);
Country japan=new Country("Japan",10000);
Country france=new Country("France",2000);
Country russia=new Country("Russia",20000);
HashMap<country,string> countryCapitalMap=new HashMap<country,string>();
countryCapitalMap.put(india,"Delhi");
countryCapitalMap.put(japan,"Tokyo");
countryCapitalMap.put(france,"Paris");
countryCapitalMap.put(russia,"Moscow");
Iterator<country> countryCapitalIter=countryCapitalMap.keySet().iterator();//установите
//debug-точку на этой строке(23)
while(countryCapitalIter.hasNext())
{
Country countryObj=countryCapitalIter.next();
String capital=countryCapitalMap.get(countryObj);
System.out.println(countryObj.getName()+"----"+capital);
}
}
}
Ahora establezca el punto de interrupción en la línea 23 y ejecute ejecutar -> depurar como-> aplicación java (nota del traductor, válida para Eclipse). El programa detendrá la ejecución en la línea 23, luego haga clic derecho en countryCapitalMap y seleccione mirar . Verá una tabla como esta: Aquí vemos lo siguiente:
-
Hay una serie
Entry[]
de 16 celdas denominadastable
; -
Esta matriz almacena objetos de la clase
Entry
. La claseHashMap
tiene una clase interna:Entry
. Y las instancias de esta clase son pares clave-valor. Echemos un vistazo a la estructura de clasesEntry
: -
Cada vez que intentamos crear un par clave-valor en un mapa hash, se creará un objeto de clase para ese par
Entry
y se almacenará en la tabla anteriorEntry[]
. Y ahora debería preguntarse dónde exactamente en esta tabla se escribirá este objeto (en qué celda). Para una clave en un par clave-valor, se calcula un código hash utilizando el archivohashcode()
. Y este código hash se utiliza para calcular el número de celda de la tablaEntry[]
; -
Ahora, si observa la celda 10 de la tabla, verá un objeto de clase
Entry
llamadoHashMap$Entry
; - Agregamos 4 pares clave-valor, ¡pero solo hay 2 en la matriz! Esto se debe a que si 2 objetos tienen el mismo código hash, se almacenarán en la misma celda. ¿Pero cómo? Los objetos se almacenarán como una lista vinculada (
LinkedList
).
static class Entry implements Map.Entry
{
final K key;
V value;
Entry next;
final int hash;
...//продолжение códigoа
}
Hashcode for Japan = 95 так Cómo длина слова Japan имеет нечетное количество букв.
Hashcode for India = 95 так Cómo длина слова India имеет нечетное количество букв.
HashCode for Russia = 31 так Cómo длина слова Russia имеет четное количество букв.
HashCode for France = 31 так Cómo длина слова France имеет четное количество букв.
La siguiente figura explicará la idea de una lista vinculada: ahora que ya comprende la estructura de los mapas hash, pasemos a los métodos put
y get
.
Poner:
Veamos cómo se utiliza este método:/**
* Метод связывает указанное significado с указанным ключом в данной хэш-карте. Если
* карта до этого уже содержала некоторое significado, соответствующее этому ключу,
* то старое significado заменяется на указанное.
* @param key
* ключ, с которым связывается указанное significado
* @param value
* significado, связываемое с указанным ключом
* @возвращает significado связанное с <tt>ключом</tt>, o <tt>null</tt>,
* если ниCómoое significado не соответствует <tt>ключу</tt>. ( Возврат <tt>null</tt>
* может так же говорить о том, что в карте заведомо <tt>null</tt> был связан с
* <tt>ключом</tt>.)
*/
public V put(K key, V value) {
if (key == null)
return putForNullKey(value);
int hash = hash(key.hashCode());
int i = indexFor(hash, table.length);
for (Entry<k , V> e = table[i]; e != null; e = e.next) {
Object k;
if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
V oldValue = e.value;
e.value = value;
e.recordAccess(this);
return oldValue;
}
}
modCount++;
addEntry(hash, key, value, i);
return null;
}
Ahora intentemos entender este código paso a paso:
-
Comprobamos la
key
igualdad del objetonull
. Si es así, entonces el objetokey
se almacenará en la ubicacióntable[0]
porque el código hashnull
es siempre 0; -
A continuación, llamamos al
key
método del objetohashcode()
, que calculará su código hash. Este código hash se utiliza para determinar la celda de la matriz donde se almacenará el objeto de claseEntry
. A veces sucede que esta funciónhashcode
no está escrita con mucha habilidad, por lo que los desarrolladores de JDK crearon una función diferente,hash()
que toma como argumento el código hash previamente calculado. Si estás interesado en leer más sobre esta función, puedes seguir el enlace ; -
indexFor(hash,table.length)
se utiliza para definir una celda específica en la matriztable
en la que se definirá un objeto de clase para ser almacenadoEntry
; -
Como vimos en nuestro ejemplo, si dos objetos
key
tienen el mismo código hash (esta situación se conoce como colisión), se almacenarán en forma de lista vinculada. Por lo tanto, en esta etapa iteramos nuestra lista: -
si la celda recién calculada está vacía, el objeto de clase
Entry
se guardará directamente en esta celda; -
si esta celda ya contiene algún objeto, se itera hasta el elemento cuyo campo es
next
igual anull
. Después de esto, nuestro objeto de claseEntry
pasa a ser el siguiente en la lista; -
¿Qué pasa si volvemos a agregar el mismo objeto
key
? Lógicamente, debería reemplazar el valor anterior. Sí, así será. Durante la iteración, las claves se compararán utilizando el métodoequals()
(key.equals(k)
). Si el resultado es verdadero, entonces el valor anterior será reemplazado por el valor del objeto actualEntry
.
Conseguir:
Ahora echemos un vistazo a la aplicación del método./**
* devoluciones significado, которое соответствует указанному ключу, o {@code null}, если
* данная карта не содержит пары с указанным ключом.
*
*
* <p>
* Более точно, если в данной карте содержится такой ключ {@code k}
* с соответствующим ему significadoм {@code v}, что {@code (key==null ? k==null : key.equals(k))},
* то метод возвращает {@code v}; в противном случае возвращается {@code null}.
* (может быть не более одной такой пары)
*
* </p><p>
* Возвращенное significado {@code null} не <i>обязательно</i> говорит о том, что
* в карте нет пары с таким указанным ключом; а возможно, что в карте однозначно
* указано соответствие этого ключа со significadoм {@code null}.
* Можно воспользоваться операцией {@link #containsKey containsKey}, чтобы
* отличить эти два случая
* @see #put(Object, Object)
*/
public V get(Object key) {
if (key == null)
return getForNullKey();
int hash = hash(key.hashCode());
for (Entry<k , V> e = table[indexFor(hash, table.length)]; e != null; e = e.next) {
Object k;
if (e.hash == hash && ((k = e.key) == key || key.equals(k)))
return e.value;
}
return null;
}
Ahora que comprende cómo funciona el método put en hashmaps, comprender cómo funciona el método put es
get
muy simple. Cuando pasas cualquier clave a un método para obtener un valor de un mapa hash:
-
Un objeto
Ekey se prueba para determinar la igualdad null
. Si es así, se devolverá el valor del objeto almacenado en la celdatable[0]
; -
El objeto clave tiene un método llamado
hashcode()
que calcula el código hash; -
indexFor(hash,table.length)
se utiliza para determinar una celda de matriz específicatable
de la cual tomar un objeto de claseEntry
; -
Después de recibir el número de celda de la matriz,
table
recorrerá la lista y comparará las claves utilizando el métodoequals()
. Si el resultado es verdadero, se devolverá el valor del objetoEntry
; de lo contrario, -null
.
Cosas para recordar:
-
La clase
HashMap
tiene una clase internaEntry
que almacena pares clave-valor; -
Los objetos de la clase
Entry
se almacenan en una matrizEntry[ ]
llamadatable
; -
Una celda de matriz se llama depósito y almacena el primer elemento de una lista vinculada;
-
El método
hashcode()
de objetokey
se utiliza para encontrar el depósito de este objeto de claseEntry
; -
Si las claves de dos objetos tienen el mismo código hash, se almacenarán en el mismo depósito de matriz
table
; -
El método
equals()
de un objetokey
se utiliza para confirmar su unicidad; -
No se utilizan métodos
equals()
nihashcode()
objetosvalue
en absoluto.
GO TO FULL VERSION