A Collection
, a veces llamado contenedor, es simplemente un objeto que agrupa múltiples elementos en una sola unidad. Collection
s se utilizan para almacenar, recuperar, manipular y comunicar datos agregados. Un marco de colecciones W es una arquitectura unificada para representar y manipular colecciones.
El HashMap
JDK1.2
y Hashtable JDK1.0
, ambos se usan para representar un grupo de objetos que están representados en <Key, Value>
pares. Cada <Key, Value>
par se llama Entry
objeto. La colección de entradas se refiere por el objeto de HashMap
y Hashtable
. Las claves de una colección deben ser únicas o distintivas. [ya que se utilizan para recuperar un valor mapeado de una clave particular. los valores en una colección se pueden duplicar.]
« Miembro de Superclass, Legacy y Collection Framework
Hashtable es una clase heredada introducida en JDK1.0
, que es una subclase de la clase Diccionario. Desde JDK1.2
Hashtable se rediseñó para implementar la interfaz de Mapa para hacer un miembro del marco de recopilación. HashMap es miembro de Java Collection Framework desde el comienzo de su introducción en JDK1.2
. HashMap es la subclase de la clase AbstractMap.
public class Hashtable<K,V> extends Dictionary<K,V> implements Map<K,V>, Cloneable, Serializable { ... }
public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable { ... }
« Capacidad inicial y factor de carga
La capacidad es el número de cubos en la tabla hash, y la capacidad inicial es simplemente la capacidad en el momento en que se crea la tabla hash. Tenga en cuenta que la tabla hash está abierta: en el caso de un " hash
collision
", un único depósito almacena múltiples entradas, que deben buscarse secuencialmente. El factor de carga es una medida de cuán llena se permite que llegue la tabla hash antes de que su capacidad aumente automáticamente.
HashMap construye una tabla hash vacía con la capacidad inicial predeterminada (16) y el factor de carga predeterminado (0.75). Donde como Hashtable construye una tabla hash vacía con una capacidad inicial predeterminada (11) y un factor de carga / relación de llenado (0.75).
« Modificación estructural en caso de colisión de hash
HashMap
, Hashtable
en caso de colisiones hash, almacenan las entradas del mapa en listas vinculadas. Desde Java8 paraHashMap
si el depósito de hash crece más allá de cierto umbral, ese depósito cambiará de linked list of entries to a balanced tree
. que mejoran el rendimiento en el peor de los casos de O (n) a O (log n). Al convertir la lista a árbol binario, el código hash se usa como una variable de ramificación. Si hay dos códigos hash diferentes en el mismo cubo, uno se considera más grande y va a la derecha del árbol y el otro a la izquierda. Pero cuando ambos códigos hash son iguales, HashMap
supone que las claves son comparables y compara la clave para determinar la dirección para que se pueda mantener un cierto orden. Es una buena práctica convertir las claves de HashMap
una . Al agregar entradas si el tamaño del depósito alcanzaTREEIFY_THRESHOLD = 8
lista de entradas enlazadas convertibles comparables en un árbol equilibrado, al eliminar entradas de menos deTREEIFY_THRESHOLD
y como máximo UNTREEIFY_THRESHOLD = 6
, árbol equilibrado en una lista vinculada de entradas. Java 8 SRC , stackpost
« Repetición de vista de colección, Fail-Fast y Fail-Safe
+--------------------+-----------+-------------+
| | Iterator | Enumeration |
+--------------------+-----------+-------------+
| Hashtable | fail-fast | safe |
+--------------------+-----------+-------------+
| HashMap | fail-fast | fail-fast |
+--------------------+-----------+-------------+
| ConcurrentHashMap | safe | safe |
+--------------------+-----------+-------------+
Iterator
es un fracaso en la naturaleza. es decir, arroja ConcurrentModificationException si se modifica una colección mientras se itera de otro modo que no sea su propio método remove (). Donde como Enumeration
es a prueba de fallas en la naturaleza. No arroja ninguna excepción si una colección se modifica durante la iteración.
De acuerdo con Java API Docs, Iterator siempre se prefiere sobre la enumeración.
NOTA: La funcionalidad de la interfaz Enumeration está duplicada por la interfaz Iterator. Además, Iterator agrega una operación de eliminación opcional y tiene nombres de método más cortos. Las nuevas implementaciones deberían considerar usar Iterator en lugar de Enumeration.
En Java 5, se introdujo la interfaz ConcurrentMap : ConcurrentHashMap
una ConcurrentMap
implementación altamente concurrente de alto rendimiento respaldada por una tabla hash. Esta implementación nunca se bloquea al realizar recuperaciones y permite al cliente seleccionar el nivel de concurrencia para las actualizaciones. Está pensado como un reemplazo directo para Hashtable
: además de implementar ConcurrentMap
, es compatible con todos los métodos "heredados" propios de Hashtable
.
HashMapEntry
El valor de cada s es volátil, lo que garantiza una consistencia de grano fino para modificaciones contenidas y lecturas posteriores; cada lectura refleja la actualización completada más recientemente
Los iteradores y las enumeraciones son a prueba de fallos, lo que refleja el estado en algún momento desde la creación del iterador / enumeración; Esto permite lecturas y modificaciones simultáneas a costa de una consistencia reducida. No lanzan ConcurrentModificationException. Sin embargo, los iteradores están diseñados para ser utilizados por un solo hilo a la vez.
Me gusta Hashtable
pero HashMap
no me gusta , esta clase no permite que se use nulo como clave o valor.
public static void main(String[] args) {
//HashMap<String, Integer> hash = new HashMap<String, Integer>();
Hashtable<String, Integer> hash = new Hashtable<String, Integer>();
//ConcurrentHashMap<String, Integer> hash = new ConcurrentHashMap<>();
new Thread() {
@Override public void run() {
try {
for (int i = 10; i < 20; i++) {
sleepThread(1);
System.out.println("T1 :- Key"+i);
hash.put("Key"+i, i);
}
System.out.println( System.identityHashCode( hash ) );
} catch ( Exception e ) {
e.printStackTrace();
}
}
}.start();
new Thread() {
@Override public void run() {
try {
sleepThread(5);
// ConcurrentHashMap traverse using Iterator, Enumeration is Fail-Safe.
// Hashtable traverse using Enumeration is Fail-Safe, Iterator is Fail-Fast.
for (Enumeration<String> e = hash.keys(); e.hasMoreElements(); ) {
sleepThread(1);
System.out.println("T2 : "+ e.nextElement());
}
// HashMap traverse using Iterator, Enumeration is Fail-Fast.
/*
for (Iterator< Entry<String, Integer> > it = hash.entrySet().iterator(); it.hasNext(); ) {
sleepThread(1);
System.out.println("T2 : "+ it.next());
// ConcurrentModificationException at java.util.Hashtable$Enumerator.next
}
*/
/*
Set< Entry<String, Integer> > entrySet = hash.entrySet();
Iterator< Entry<String, Integer> > it = entrySet.iterator();
Enumeration<Entry<String, Integer>> entryEnumeration = Collections.enumeration( entrySet );
while( entryEnumeration.hasMoreElements() ) {
sleepThread(1);
Entry<String, Integer> nextElement = entryEnumeration.nextElement();
System.out.println("T2 : "+ nextElement.getKey() +" : "+ nextElement.getValue() );
//java.util.ConcurrentModificationException at java.util.HashMap$HashIterator.nextNode
// at java.util.HashMap$EntryIterator.next
// at java.util.Collections$3.nextElement
}
*/
} catch ( Exception e ) {
e.printStackTrace();
}
}
}.start();
Map<String, String> unmodifiableMap = Collections.unmodifiableMap( map );
try {
unmodifiableMap.put("key4", "unmodifiableMap");
} catch (java.lang.UnsupportedOperationException e) {
System.err.println("UnsupportedOperationException : "+ e.getMessage() );
}
}
static void sleepThread( int sec ) {
try {
Thread.sleep( 1000 * sec );
} catch (InterruptedException e) {
e.printStackTrace();
}
}
«« Claves nulas y valores nulos
HashMap
permite un máximo de una clave nula y cualquier número de valores nulos. Donde as Hashtable
no permite ni siquiera una sola clave nula y un valor nulo, si la clave o el valor nulo es entonces arroja NullPointerException.Ejemplo
«« Sincronizado, hilo seguro
Hashtable
está sincronizado internamente Por lo tanto, es muy seguro de usar Hashtable
en aplicaciones de subprocesos múltiples. Donde como HashMap
no está sincronizado internamente. Por lo tanto, no es seguro usarlo HashMap
en aplicaciones de subprocesos múltiples sin sincronización externa. Puedes sincronizar externamenteHashMap
utilizando el Collections.synchronizedMap()
método
«« Rendimiento
Como Hashtable
está sincronizado internamente, esto hace que sea un Hashtable
poco más lento que elHashMap
.
@Ver