Serie de entrevistas Java - HashMap

Cuando vi una entrevista relacionada con Java recientemente, vi una entrevista sobre HashMap y ¡me sentí bastante bien! Los sitios de entrevistas actuales no se enfocarán en cierto conocimiento para que el entrevistador lo elabore, pero le permitirán elaborar a través de una serie de preguntas relacionadas, y luego formar un punto a línea, y luego de línea a superficie para examinar las habilidades básicas y la divergencia. del entrevistador Pensamiento sexual. ¡Entra sin cesar, sabiendo que no puedes responder o que el entrevistador te pide el final!

Entrevistador: 1. ¿Conoce / usa HashMap? ¿Por qué utilizar HashMap?

¡Creo que puedes responder a esta pregunta más o menos algún conocimiento relevante, como algunas características (ventajas)! ¡Esto es solo un preludio para examinar su HashMap!

tal como:

  1. HashMap es un depósito de hash (hablando intuitivamente de las características de la estructura de datos de HashMap: matriz y lista vinculada), almacena el mapeo clave-valor (pares clave-valor)
  2. HashMap adopta la estructura de datos de la matriz y la sección de lista vinculada, lo que puede facilitar la herencia de la búsqueda lineal de la matriz y la modificación del direccionamiento de la lista vinculada en la consulta y modificación para mejorar la eficiencia.
  3. HashMap no es seguro (no está sincronizado), por lo que la velocidad es muy rápida si la seguridad no está garantizada
  4. HashMap puede ser nulo tanto para la clave como para el valor, pero Hashtable no puede (la razón es que Hashtable usa el método igual para generar una excepción de puntero nulo, y HashMap ha sido procesado por la API, que no aparecerá en este caso)
  5. y muchos más

La respuesta está aquí, creo que el entrevistador ya sabe que usted conoce y usa HashMap, pero el entrevistador dará un giro rápido y hará algunas preguntas difíciles o vagas al respecto, como algunas preguntas específicas y detalladas.

 

Entrevistador: 2. ¿Sabes cómo funciona HashMap? ¿Sabes cómo funcionan los métodos put y get de HashMap?

! ! ? ? ¡Yo voy! ¡Confundido! Tal vez utilices HashMap muy 666, pero ¿cómo funciona? Emma! ¡Realmente no hay un estudio en profundidad! Si realmente no lo sabe, significa que este tema ha terminado, pero si dice algunas preguntas incorrectas, ¡es muy peligroso! La entrevista es para decir si lo sabe, y si no lo sabe, simplemente diga que no sabe, ¡la actitud es muy importante! !

¡Vamos, echemos un vistazo a las cosas examinadas en esta pregunta!

En cuanto a la primera pregunta:

¡HashMap se basa en el principio de hash! El uso de HashMap se basa en el principio de hash. Usamos put (clave, valor) para almacenar objetos en HashMap, y usamos get (clave) para obtener objetos de HashMap. Cuando pasamos la clave y el valor al método put (), primero llamamos al método hashCode () en la clave, y el hashCode devuelto se usa para encontrar la ubicación del depósito para almacenar el objeto Entry.

Hasta ahora, ha respondido al principio de funcionamiento de HashMap, pero (el punto clave es que HashMap almacena objetos clave y de valor en el backet, como el nodo Map.Entry of the Map) , esto es propicio para el principio de funcionamiento de obtener objetos correspondiente al método get Si no es consciente de esto, no solo puede pensar que solo almacenando el valor en el backet, no puede responder cómo obtener el objeto.

 Simplifica y simula la estructura de datos.

Node[] table = new Node[16];    //散列桶初始化,table

// 节点数据结构
class Node{
    int hash;    // hash值
    key;         // 键
    value;       // 值
    Node next;   // 用于指向链表的下一层(产生冲突,使用拉链法)
}

En cuanto a la segunda pregunta:

poner código fuente

public V put(K key, V value) {
    return putVal(hash(key), key, value, false, true);
}

El proceso de venta se puede dividir aproximadamente en las siguientes etapas (para el jdk1.8 de uso común)

  1. Cálculo del valor hash (método hash) en el valor clave y luego calcular el subíndice
  2. Si el objeto clave no existe en el backet, se almacena directamente en el depósito (también llamado colisión)
  3. Si el objeto clave existe, se almacenará en una lista vinculada y se vinculará en la parte posterior
  4. Si la longitud de la lista vinculada excede el umbral (TREEIFY THRESHOLD == 8), la lista vinculada se convertirá en un árbol rojo-negro, y si la longitud de la lista vinculada es menor que 6, el árbol rojo-negro se convertirá convertirse en una lista vinculada
  5. Si el nodo existe, se reemplazará el valor anterior
  6. Si el depósito está lleno (capacidad 16 * factor de carga 0,75), se cambiará de tamaño (se ampliará 2 veces y se reorganizará)

obtener el código fuente

public V get(Object key) {
    Node<K,V> e;
    return (e = getNode(hash(key), key)) == null ? null : e.value;
}

¿Cómo consigue el objeto?

Para el método put anterior, es mucho más simple para el método get

Cuando llamamos al método get, HashMap usará el código hash del objeto clave para encontrar la ubicación del depósito. Después de encontrar la ubicación del depósito, llamará al método keys.equal () para encontrar el nodo correcto en la lista vinculada, y finalmente encuentra el objeto de valor

Quizás lo anterior sea solo el comienzo de la historia de HashMap El entrevistador le hará preguntas sobre su dominio en el desarrollo diario.

 

Entrevistador: 3. ¿Qué sucede cuando los códigos hash de dos objetos son iguales?

La primera reacción a esta pregunta debería ser: ¡Me voy, estoy avergonzado de nuevo! !

A partir de aquí comienza la verdadera confusión, algunos entrevistadores responderán que debido a que el código hash es el mismo, los dos objetos son iguales, el HashMap lanzará una excepción, o no se almacenarán, etc., ¡varias respuestas son variadas! Entonces, el entrevistador puede recordarle los dos métodos de hashcode e igual, o algunos entrevistadores pueden abandonar la entrevista directamente.Por supuesto, esto termina la pregunta sobre HashMap.

Por supuesto, algunos entrevistadores excelentes continuarán avanzando: si los códigos hash son iguales, se puede juzgar que las posiciones de sus cubos son las mismas, lo que provocará una "colisión", porque HashMap usa una lista vinculada para almacenar objetos, esta Entrada ( Objeto Map.Entry que contiene pares clave-valor)) Almacenará la lista vinculada . La respuesta es acertada y muy razonable. Aunque hay muchas formas de lidiar con las colisiones, este método es el más simple y realmente es la forma de lidiar con HashMap.

Sin embargo, la historia no ha terminado y el problema continuará. Bros! Esperar....,

 

Entrevistador: 4. Si el código hash de las dos claves es el mismo, ¿cómo obtendría el objeto de valor?

Por supuesto, el objeto de valor del Mapa debe obtenerse a través del método get, ¡así que vamos al burro en torno al principio de funcionamiento del método get! Sin embargo, no es suficiente ¡Yo! Esta no es la respuesta que quiere el entrevistador, de lo contrario la pregunta no aparecerá (¡¡¡ya te han preguntado arriba !!!).

Entrevistador : Cuando llamamos al método get, HashMap usará el valor del código hash del objeto clave para encontrar la ubicación del depósito y luego obtendrá el objeto de valor.

Entrevistador : ¿Qué pasa si hay dos o más cubos en la misma posición?

Entrevistador : HashMap recorrerá la lista enlazada hasta que encuentre el objeto de valor correspondiente.

Entrevistador : No tienes objetos de valor para comparar, ¿cómo te aseguras de encontrar objetos de valor? (A menos que los entrevistados hasta que HashMap almacene pares clave-valor en la lista vinculada, no podrán responder esta pregunta).

Recuerde que HashMap almacena objetos clave y de valor en el backet como el mapa de nodo. ¿Entrada del mapa ? Entonces el problema se simplifica

Entrevistador : Después de encontrar la ubicación del depósito, llamará al método keys.equals () para encontrar el nodo correcto en la lista vinculada y, finalmente, encontrará el objeto de valor que está buscando. (¡Respuesta perfecta!)

En muchos casos, los entrevistadores cometerán errores en este enlace porque confunden los métodos hashCode () y equals () . Porque el hashCode () apareció repetidamente antes de esto, y el método equals () solo apareció cuando se obtuvo el objeto de valor. Algunos buenos desarrolladores señalarán que el uso de objetos finales declarados inmutables y el uso de métodos equals () y hashCode () apropiados reducirán las colisiones y mejorarán la eficiencia. La inmutabilidad permite almacenar en caché el código hash de diferentes claves, lo que aumentará la velocidad de la adquisición de todo el objeto . Es una muy buena opción utilizar clases contenedoras como String e Interger como claves .

Si crees que se acabó, cuando escuches la siguiente pregunta, colapsarás o te pondrás nervioso.

 

Entrevistador: 5. ¿Qué pasa si el tamaño del HashMap excede la capacidad definida por el factor de carga?

A menos que realmente comprenda cómo funciona HashMap, no podrá responder ...

Al mismo tiempo, después de hacer esta pregunta, tenga en cuenta que el entrevistador le presentará la seguridad de subprocesos de manera oportuna y esté preparado.

Puedes responder así:

Cuando los datos son demasiado grandes, Map realizará un refrito.

El tamaño del factor de carga predeterminado es 0,75, es decir, cuando un mapa llena el 75% de los depósitos, como otras colecciones (como Array, etc.), se creará una matriz de depósitos con el doble del tamaño del HashMap original para su reajuste. El tamaño del mapa y coloque los objetos originales en la nueva matriz de cubos. Este proceso se repite en el tiempo, después de todo, en este proceso, se llama al método hash para encontrar una nueva ubicación de depósito.

Él respondió que ahora, el entrevistador no me soltará, y luego te preguntará.

 

Entrevistador: 6. ¿Sabe qué hay de malo en cambiar el tamaño de HashMap?

Este problema es a menudo en el caso de subprocesos múltiples, por supuesto, debe comprender la competencia condicional ; de lo contrario, aún no puede encontrar un punto de entrada.

Cuando se ajusta el tamaño del mapa, habrá competencia condicional, porque en condiciones de subprocesos múltiples, ambos subprocesos encuentran que el HashMap necesita ser redimensionado, luego intentarán ajustar al mismo tiempo. Durante el proceso de ajuste, el orden de los elementos almacenados en la LinkedList se mostrarán en el Arrangement (porque cuando se mueve a una nueva posición del cubo, HashMap colocará los elementos en la cabeza de la LinkedList en lugar de en la cola, para atravesar la cola). Una vez que ocurra la competencia condicional, habrá un ciclo sin fin.

Las preguntas se guían paso a paso. Cuanto más responda, más cosas podrá dominar. ¡Esto es inevitable!

La pregunta viene de, ¡el entrevistador te seguirá preguntando!

 

Entrevistador: 7. ¿Por qué el subproceso múltiple conduce a un bucle infinito y cómo sucede?

¡Cómo! ? El entrevistador te guiará paso a paso de acuerdo a tus respuestas, si realmente sabes la respuesta a la pregunta anterior no te preocupes demasiado por la siguiente pregunta, por el contrario, cuando estés ciego, serás entrevistado por el entrevistador.Ver paso a paso, ¡el resultado final será muy embarazoso! Entonces, es el mismo principio, si no lo entiende, simplemente sáltelo, ¡no diga tonterías!

El avance de este problema es ¿cuál es la fuente del bucle infinito? En gran medida, el bucle infinito es causado por la configuración de la estructura de datos y el funcionamiento incorrecto de los datos. Por lo tanto, ¡debe conocer muy bien la estructura de datos de HashMap! Así es, es una matriz + lista vinculada (después de JDK8 es una matriz + lista vinculada + árbol rojo-negro). ¿Formación? ¡La estructura lineal no producirá un bucle sin fin de todos modos! Luego hay una lista vinculada (la lista vinculada es fácil de generar bucles ). ¡Correcto! ¡es él! Las listas vinculadas son exactamente cómo HashMap maneja las colisiones.

La capacidad de HashMap es limitada. Cuando se insertan varios elementos, el HashMap alcanza un cierto grado de saturación (cerca del factor de carga 0,75) y la probabilidad de conflictos en la posición de mapeo clave aumentará gradualmente. En este momento, HashMap necesita expandir su longitud, es decir, cambiar el tamaño (expansión).

(Por supuesto, en este momento, puedes muestrear al entrevistador: Es muy extraño, ¿por qué usar HashMap en multi-threading? Jejeje, durante el proceso de entrevista, no solo el entrevistador te pregunta, sino también en circunstancias irrazonables, también puedes preguntar volver Entrevistador, esto hará que el entrevistador se sienta único, ¡los llamados maestros del arte son audaces!)

 

Entrevistador: 8. Si quiero usar HashMap para implementar multi-threading, ¿puedo hacerlo?

¡Jajaja! ¡Esta vez es probablemente la respuesta del entrevistador a tu pregunta disfrazada! Esto examinará el HashMap en múltiples subprocesos.Hay muchos métodos como bloquear (extremadamente no recomendado, pero puede responderse), usar el método de encapsulación en Colecciones o usar otras clases con el mismo efecto en su lugar, y así sucesivamente.

por supuesto. Puede utilizar java.util.Collections.synchronizedMap (Map) para el procesamiento . (Esta es la respuesta más simple y efectiva. El entrevistador no puede encontrar ningún defecto, incluso si conoce ConcurrentHashMap, etc.) Una respuesta simple es suficiente. En cuanto a otras preguntas, simplemente responda nuevamente. Debe saber cómo converger en una manera oportuna. de! !

 

¡Jajaja! Después de una serie de preguntas, ¿puede comprender el método de entrevista? En realidad, es un análisis integral del problema, no solo en profundidad, sino también en amplitud. Entonces, amigos míos, usen Kung Fu en tiempos normales, ¡y no tendrán prisa!

---------------------
Autor: Codificación mundial
Fuente: CSDN
Original: https://blog.csdn.net/dgxin_605/article/details/86249771
Copyright: Este El artículo es el artículo original del blogger, ¡adjunte un enlace a la publicación del blog si lo reimprime! !

 

Supongo que te gusta

Origin blog.csdn.net/dgxin_605/article/details/86249771
Recomendado
Clasificación