A Collection
- às vezes chamado de contêiner - é simplesmente um objeto que agrupa vários elementos em uma única unidade. Collection
s são usados para armazenar, recuperar, manipular e comunicar dados agregados. Uma estrutura de coleções W é uma arquitetura unificada para representar e manipular coleções.
O HashMap
JDK1.2
e Hashtable JDK1.0
, ambos são usados para representar um grupo de objetos que são representados em <Key, Value>
par. Cada <Key, Value>
par é chamado de Entry
objeto. A coleção de entradas é referida pelo objeto de HashMap
e Hashtable
. As chaves em uma coleção devem ser únicas ou distintas. [como eles são usados para recuperar um valor mapeado de uma chave específica. os valores em uma coleção podem ser duplicados.]
« Membro da Superclasse, Legado e Estrutura de Coleta
Hashtable é uma classe herdada introduzida em JDK1.0
, que é uma subclasse da classe Dictionary. Do JDK1.2
Hashtable é reprojetado para implementar a interface do Mapa para tornar um membro da estrutura de coleta. O HashMap é um membro do Java Collection Framework desde o início de sua introdução no JDK1.2
. HashMap é a subclasse da classe 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 { ... }
« Capacidade inicial e fator de carga
A capacidade é o número de buckets na tabela de hash e a capacidade inicial é simplesmente a capacidade no momento em que a tabela de hash é criada. Observe que a tabela de hash está aberta: no caso de " hash
collision
", um único bloco armazena várias entradas, que devem ser pesquisadas sequencialmente. O fator de carga é uma medida de quão cheia é permitida a tabela de hash antes que sua capacidade seja aumentada automaticamente.
O HashMap constrói uma tabela de hash vazia com a capacidade inicial padrão (16) e o fator de carga padrão (0,75). Onde como Hashtable constrói hashtable vazio com uma capacidade inicial padrão (11) e fator de carga / razão de preenchimento (0,75).
« Modificação estrutural em caso de colisão de hash
HashMap
, Hashtable
no caso de colisões de hash, eles armazenam as entradas do mapa em listas vinculadas. Do Java8 paraHashMap
se o hash bucket crescer além de um determinado limite, esse bucket mudará de linked list of entries to a balanced tree
. que melhoram o desempenho do pior caso de O (n) para O (log n). Ao converter a lista em árvore binária, o hashcode é usado como uma variável ramificada. Se houver dois códigos de hash diferentes no mesmo bucket, um é considerado maior e vai para a direita da árvore e outro para a esquerda. Mas quando os dois HashMap
códigos de hash são iguais, assume que as chaves são comparáveis e compara a chave para determinar a direção, para que alguma ordem possa ser mantida. É uma boa prática tornar as chaves HashMap
comparáveis . Ao adicionar entradas se o tamanho do balde atingirTREEIFY_THRESHOLD = 8
converta a lista vinculada de entradas em uma árvore balanceada, ao remover entradas menoresTREEIFY_THRESHOLD
e no máximo UNTREEIFY_THRESHOLD = 6
reconverterá a árvore balanceada na lista vinculada de entradas. Java 8 SRC , stackpost
« Iteração de exibição de coleção, Fail-Fast e Fail-Safe
+--------------------+-----------+-------------+
| | Iterator | Enumeration |
+--------------------+-----------+-------------+
| Hashtable | fail-fast | safe |
+--------------------+-----------+-------------+
| HashMap | fail-fast | fail-fast |
+--------------------+-----------+-------------+
| ConcurrentHashMap | safe | safe |
+--------------------+-----------+-------------+
Iterator
é uma natureza à prova de falhas. ou seja, lança ConcurrentModificationException se uma coleção é modificada enquanto itera diferente de seu próprio método remove (). Enquanto queEnumeration
é à prova de falhas na natureza. Não lança nenhuma exceção se uma coleção for modificada durante a iteração.
De acordo com a Java API Docs, o Iterator é sempre preferido sobre a Enumeração.
NOTA: A funcionalidade da interface de enumeração é duplicada pela interface do iterador. Além disso, o Iterator adiciona uma operação de remoção opcional e possui nomes de métodos mais curtos. Novas implementações devem considerar o uso do Iterator em vez da Enumeração.
Em Java 5, introduziu a Interface ConcurrentMap : ConcurrentHashMap
- uma ConcurrentMap
implementação altamente simultânea e de alto desempenho, apoiada por uma tabela de hash. Essa implementação nunca bloqueia ao executar recuperações e permite que o cliente selecione o nível de simultaneidade para atualizações. Ele foi concebido como um substituto para Hashtable
: além da implementação ConcurrentMap
, ele suporta todos os métodos "herdados" peculiares Hashtable
.
HashMapEntry
O valor de cada s é volátil , garantindo, assim, consistência de granulação fina para modificações contidas e leituras subsequentes; cada leitura reflete a atualização concluída mais recentemente
Iteradores e enumerações são à prova de falhas - refletindo o estado em algum momento desde a criação do iterador / enumeração; isso permite leituras e modificações simultâneas ao custo de consistência reduzida. Eles não lançam ConcurrentModificationException. No entanto, os iteradores são projetados para serem usados por apenas um encadeamento por vez.
De maneira semelhante, Hashtable
mas diferente HashMap
, essa classe não permite que nulo seja usado como chave ou 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();
}
}
« Chaves nulas e valores nulos
HashMap
permite no máximo uma chave nula e qualquer número de valores nulos. Onde as Hashtable
não permite nem mesmo uma única chave nula e um valor nulo, se a chave ou o valor nulo for, ele lançará NullPointerException. Exemplo
« Sincronizado, Thread Safe
Hashtable
é sincronizado internamente. Portanto, é muito seguro usar Hashtable
em aplicativos multithread. Onde como HashMap
não é sincronizado internamente. Portanto, não é seguro usar HashMap
em aplicativos multithread sem sincronização externa. Você pode sincronizar externamente HashMap
usando o Collections.synchronizedMap()
método
« Desempenho
Como Hashtable
é sincronizado internamente, isso torna Hashtable
um pouco mais lento que o HashMap
.
@Vejo