HashMap jdk1.7 en el "error grave": lista circular
configuración jdk1.7 HashMap en la figura.
jdk1.7 es una lista enlazada estructura array +
versiones jdk1.7 existen dos problemas principales
-
El caso resultará en la cadena de ciclo primera interpolación
-
La lista es demasiado larga, que dará lugar a la investigación eficacia reducida
versión jdk1.8 optimizado para jdk1.8
- Tail utilizando interpolación, la eliminación se produce lista circular
- Después de la lista es demasiado larga, en un árbol rojo-negro, mejorar la eficiencia de la consulta
Me refiero específicamente a otro artículo de blog que realmente saben los fabricantes se enfrentan a preguntas: HashMap que?
Producir lista circular
Multithreading Mientras tanto put
, si al mismo tiempo llamando a la resize
operación podría conducir a la lista circular se genera, con lo que el tiempo para volver, será un bucle sin fin. La siguiente detalle la forma circular de forma de lista.
la función de cambio de tamaño
función de expansión Array, la función principal es la de crear una nueva matriz después de la expansión, y llama a la transfer
función migrará los viejos elementos de la matriz a una nueva matriz
void resize(int newCapacity)
{
Entry[] oldTable = table;
int oldCapacity = oldTable.length;
......
//创建一个新的Hash Table
Entry[] newTable = new Entry[newCapacity];
//将Old Hash Table上的数据迁移到New Hash Table上
transfer(newTable);
table = newTable;
threshold = (int)(newCapacity * loadFactor);
}
función de transferencia
lógica de transferencia es realmente simple, que atraviesa la matriz de edad, el elemento de la matriz por el viejo interpolación cabecera manera, la posición correspondiente a migrar a las nuevas mentiras de problemas en una matriz de interpolación cabeza .
void transfer(Entry[] newTable)
{
//src旧数组
Entry[] src = table;
int newCapacity = newTable.length;
for (int j = 0; j < src.length; j++) {
Entry<K,V> e = src[j];
if (e != null) {
src[j] = null;
do {
Entry<K,V> next = e.next;
int i = indexFor(e.hash, newCapacity);
e.next = newTable[i];
newTable[i] = e;
e = next;
} while (e != null);//由于是链表,所以有个循环过程
}
}
}
static int indexFor(int h, int length){
return h&(length-1);
}
He aquí un ejemplo de práctica
//下面详细解释需要用到这部分代码,所以先标号,将一下代码分为五个步骤
do {
1、Entry<K,V> next = e.next;
2、int i = indexFor(e.hash, newCapacity);
3、e.next = newTab[i];
4、newTable[i] = e;
5、e= next;
} while(e != null)
-
empezar capacidad se establece en 2, se carga el valor de umbral
-
hilo e hilo Mientras tanto insertar elementos, ya que el valor umbral es 1, por lo que la necesidad de llamar a
resize
la función, la operación para la expansión -
hilo En primer lugar el bloqueo del código
Entry<K,V> next = e.next;
, después de hilo Después de ejecutar expansión de las operaciones -
después de hilo Despertar, continuar, después de la finalización de un ciclo
empezar , , la aplicación del código siguiente, ,
2、int i = indexFor(e.hash, newCapacity); 3、e.next = newTab[i]; 4、newTable[i] = e; 5、e= next; 1、Entry<K,V> next = e.next;
-
hilo Después de la implantación del segundo ciclo
empezar , , se ejecuta el código siguiente, $ e \ rightarrow3 $,
2、int i = indexFor(e.hash, newCapacity); 3、e.next = newTab[i]; 4、newTable[i] = e; 5、e= next; 1、Entry<K,V> next = e.next;
-
Después de la tercera ejecución del ciclo hilo T1, formando un bucle sin fin
empezar , , el código siguiente,
2、int i = indexFor(e.hash, newCapacity); 3、e.next = newTab[i]; 4、newTable[i] = e; 5、e= next; 1、Entry<K,V> next = e.next;