I. Introducción
El mes pasado, se tomó un tiempo para estudiar un poco HashMap
del código fuente de HashMap
la aplicación de los principios tienen una mayor comprensión en profundidad de hoy de repente pensar en una prueba a menudo se enfrentan con cuestiones - HashMap
con Hashtable
una diferencia, por lo que tomó un tiempo para estudiar un poco Hashtable
fuente. Hoy en día, en este blog para explicar brevemente la diferencia entre los dos, lo siguiente será sobre todo desde el Hashtable
punto de vista, describirlo y HashMap
cuál es la diferencia, y se describirá en dos aspectos - el uso de términos y detalles de realización . Si HashMap
no es muy comprensivo, se puede leer acerca de este blog: HashMap Interpretación fuente - la comprensión de la profundidad HashMap causa eficiente .
En segundo lugar, el texto
Las diferencias de 2.1
(1) Hashtable thread-safe, HashMap hilo-inseguro
Esta es la diferencia fundamental entre los dos vasos. HashMap
Es un contenedor seguro para subprocesos, que no implementa la sincronización de hilos, por lo que no se debe utilizar en un entorno multiproceso. La Hashtable
realización de la sincronización de hilos, es un contenedor seguro para subprocesos, pero compara manera sincronizada mal - la adición sincronizada palabra clave directamente en la mayoría de los métodos públicos para sincronizar , por lo que para los mismos Hashtable
objetos, que sólo puede tener una subproceso llama que un método de instancia. De esta manera torpe que el sincronizada Hashtable
eficiencia es mucho menor que HashMap
, y en muchos casos, esta sincronización no tiene sentido, como en el caso de una operación de escritura no está ocurriendo, pueden simultáneamente múltiples hilos de Hashtable
leer, y no causará daño.
(2) Hashtable permitió clave o el valor es nulo, lata HashMap
En Hashtable
muchos sentidos, el (como el put
método), condenado especial value
para la null
situación, momento en el que un tiro directo NullPointerException
; Para key
que null
la situación no tiene sentencia especial, pero si se añade en una key
de las null
elementos, siendo los tiros NullPointerException
, desde Hashtable
la adquisición key
de hash
los valores es llamar a la directa key.hashCode
método, todo key
no puede ser null
. Vemos Hashtable
el put
método para saber (se borra el código adicional):
public synchronized V put(K key, V value) {
// Make sure the value is not null
if (value == null) {
throw new NullPointerException();
}
// ......
int hash = key.hashCode();
// ......
}
Sin embargo HashMap
, si se trata key
o value
, se puede pensar null
, ya que null
hizo un tratamiento especial. HashMap
Implementación, el juez key
es null
, no va a ser llamado key.hashCode
para obtener su hash
valor, sino más bien 0
como su hash
valor, y en el get
método de adquirir value
, si no se encuentra el nodo null
, entonces el retorno directo null
, de lo contrario node.value
. Busque también en HashMap
las dos piezas de código para verificar lo siguiente:
// 此方法为HashMap中获取key的hash值的方法,特判了key == null的情况
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
// HashMap中的get方法,特判了value为null的情况
public V get(Object key) {
Node<K,V> e;
return (e = getNode(hash(key), key)) == null ? null : e.value;
}
2.2 darse cuenta de las diferencias en los detalles
(1) la cabeza Hashtable utilizando interpolación, la interpolación HashMap usando la cola después de JDK1.8
hablar brevemente sobre lo que es el primer enchufe y el final del juego:
- El primer método de interpolación: Insertar un nuevo nodo en la lista vinculada, la lista enlazada el nuevo nodo como el nodo primario, y el nuevo nodo
next
apunta al nodo de cabecera de edad; - Tail Interpolación: Cuando se inserta un nuevo nodo en la lista, por lo que el final de la lista de nodos vinculados
next
puntos al nuevo nodo;
Hashtable
En primer lugar se utiliza la interpolación, pero HashMap
en JDK1.8
el uso anterior es la interpolación cabeza. Sin embargo, se encontró que en el caso concurrente, si no hay sincronización de subprocesos, el primer método de interpolación hay una pequeña probabilidad dará lugar a un bucle infinito (no voy a empezar a este problema se describe, puede ir a buscar hacia arriba), por lo que desde el JDK1.8
principio, como HashMap
la adición de un nodo hasta el final de la interpolación.
(2) Capacidad HashMap debe ser 2 ^ n, y la capacidad no es el límite Hashtable
Esta es una diferencia muy grande entre los dos, en este punto, por lo que HashMap
y Hashtble
son muy diferentes en su aplicación. HashMap
La capacidad debe ser 2^n
la razón por la que recomiendo en el blog prefacio que hizo una descripción detallada, simplemente haga clic aquí. Capacidad como 2^n
se hace con el fin de optimizar el módulo aritmético como 2^n
para satisfacer una propiedad:
Seguramente% 2 ^ n == si, y (2 ^ n - 1)
Ya sea HashMap
o Hashtable
, para obtener el índice de nodo de la matriz, necesidad de utilizar key
el hash
valor de módulo de la longitud de la matriz, y HashMap
el límite de longitud de la matriz 2^n
, es utilizar la fórmula anterior &
Alternativamente %
realizado operación de módulo, porque &
eficiente que %
superior, mientras que la adquisición de índice es una operación frecuente, por lo que este paso se optimiza de manera que HashMap
la velocidad de búsqueda se ha mejorado mucho. En el Hashtable
medio, que es el uso directo %
de más de toma. Vemos más de cualquier fuente:
// HashMap中的取余:tab为存放节点的数组,n为数组长度,hash变量存的是key的哈希值
// 这一步就是获取哈希值为hash的key在tab中的位置
// HashMap中的hash值不会是负数,因为HashMap中自己实现了hash方法求hash值
tab[(n - 1) & hash]
// Hashtable中的取余:hash & 0x7FFFFFFF其实就是取hash的绝对值,然后直接对tab.length取余
// 0x7FFFFFFF转换成二进制就是第一位为0,后31位为1,这个操作也就是将符号位转为0(第一位为符号位),
// 而二进制中,符号位为0表示表示正数,这一步是防止计算出负数的下标,因为hash值可能为负
// 不用Math.abs是因为Math.abs(Integer.MAX_VALUE)越界,结果还是负数
int index = (hash & 0x7FFFFFFF) % tab.length;
Y es esta optimización, lo que lleva HashMap
y Hashtable
muchas otras diferencias:
HashMap
La capacidad inicial por defecto16
, es decir2^4
, si una capacidad especificada esHashMap
no usarlo directamente, pero primero encontrar la primera es mayor que la capacidad especificada2^n
y;Hashtable
capacidad inicial por defecto11
,11
es un número primo, de acuerdo conhash
los requisitos escala de tiempo, de modo que el siguiente número primo se puede asignar subíndice más uniforme,Hashtable
que recibe directamente la capacidad inicial especificada;HashMap
Directamente a la tamaño de la matriz multiplicado cuando la expansión2
, ya que(2^n)×2 == 2^(n+1)
, aún así cumplir2^n
; yHashtable
expansión Shi乘2加1
, ya que permite una gran probabilidad número primo o un número primo;
(3) JDK1.8 comenzó, estructura de la cadena HashMap + en una matriz de árbol + rojo-negro
En JDK1.7
el pasado, HashMap
y Hashtable
la estructura es una implementación de matriz + lista enlazada, pero desde el JDK1.8
principio, HashMap
en una lista enlazada de arrays + + árbol rojo-negro. Esto es porque, en el hash
caso en el que la irregularidad de módulo resultado, el nodo puede ser concentrada en unos pocos array lista, resultando en una larga lista. Por ejemplo, un ejemplo extremo, todos los nodos hash
calculan los valores de índice son iguales, entonces todos los nodos en una lista enlazada, esta vez HashMap
o Hashtable
a degenerar en una lista enlazada, la complejidad de tiempo de consulta para la degradación O(n)
. Para evitar que esto suceda, desde el JDK1.8
principio, HashMap
en Si una lista enlazada de nodos alcanzó 8
uno, puso esta lista se convierte en un árbol rojo-negro, esta vez, recogidos en este artículo la eficacia de las consultas a partir O(n)
promovido O(logn)
. Y Hashtable
como un contenedor obsoleta, la naturaleza no se tomará el tiempo para optimizar su complejo.
En tercer lugar, el resumen
Hashtable
Es un buque obsoleto, en el desarrollo, que debe ser inferior a usarlo, o simplemente no lo usamos. En el entorno de un solo roscado, que usaríamos HashMap
, pero en un entorno multiproceso, debe ser usado ConcurrentHashMap
, su eficiencia es mucho mayor Hashtable
. Algunos mencionado en último lugar son relevantes y lograr HashMap, recomiendo leer las recomendaciones en el blog prefacio para HashMap
la aplicación específica.