Diferenças entre HashMap e Hashtable?

3750

Quais são as diferenças entre a HashMape a Hashtableem Java?

Qual é mais eficiente para aplicativos não encadeados?

dmanxiii
fonte
17
HashTable é obsoleto em Java 1.7 e recomenda-se usar a execução ConcurrentMap
MissFiona
@ MissFiona Não, nãoConcurrentMap é necessário aqui, pois a pergunta diz "aplicativos não encadeados", o que significa que a segmentação / simultaneidade não é um problema.
Basil Bourque

Respostas:

3775

Existem várias diferenças entre HashMape Hashtableem Java:

  1. Hashtableestá sincronizado , enquanto HashMapnão está. Isso HashMapmelhora para aplicativos não encadeados, pois os objetos não sincronizados geralmente têm melhor desempenho do que os sincronizados.

  2. Hashtablenão permite nullchaves ou valores. HashMappermite uma nullchave e qualquer número de nullvalores.

  3. Uma das subclasses do HashMap é que LinkedHashMap, caso você deseje uma ordem de iteração previsível (que é a ordem de inserção por padrão), você pode facilmente trocar a HashMappor a LinkedHashMap. Isso não seria tão fácil se você estivesse usando Hashtable.

Como a sincronização não é um problema para você, eu recomendo HashMap. Se a sincronização se tornar um problema, você também pode olhar ConcurrentHashMap.

Josh Brown
fonte
84
Se você deseja tornar um HashMap seguro para threads, use Collections.synchronizedMap().
Rok Strniša
275
Eu também comentaria que a abordagem ingênua da segurança de threads Hashtable("sincronizar todos os métodos deve cuidar de qualquer problema de simultaneidade!") Torna muito pior para aplicativos de threads. É melhor sincronizar externamente um HashMap(e pensar nas consequências) ou usar uma ConcurrentMapimplementação (e explorar sua API estendida para simultaneidade). Conclusão: o único motivo para usar Hashtableé quando uma API herdada (de cerca de 1996) exige.
Erickson
8
O HashMap oferece flexibilidade ao programador para escrever código threadSafe quando ele realmente o usa. Raramente acontecia que eu precisasse de uma coleção segura de threads, como ConcurrentHashMap ou HashTable. O que eu precisava era de um certo conjunto de funções ou de determinadas instruções em um bloco sincronizado para ser seguro para threads.
Gaurava Agarwal
2
O Hashtable é obsoleto e estamos usando o HashMap para um ambiente seguro sem thread. Se você precisar de segurança de encadeamento, poderá usar Collections.synchronizedMap () ou ConcurrentHashMap, que é mais eficiente que a hashtable.
Maneesh Kumar
1
É obsoleto, mas não obsoleto e estou me perguntando por que isso acontece. Suponho que remover esta classe (e Vector pelas mesmas razões) quebraria muito código existente e fazer anotações com @Deprecated implicaria uma intenção de remover o código, o que aparentemente não existe.
Jilles van Gurp 19/05/19
682

Observe que muitas respostas afirmam que o Hashtable está sincronizado. Na prática, você compra muito pouco. A sincronização está nos métodos de acessador / mutador interromperá a adição ou remoção de dois encadeamentos do mapa simultaneamente, mas no mundo real, muitas vezes você precisará de sincronização adicional.

Um idioma muito comum é "verificar e colocar" - ou seja, procure uma entrada no Mape adicione-a se ela ainda não existir. Isso não é de forma alguma uma operação atômica, se você usa Hashtableou HashMap.

Uma sincronização equivalente HashMappode ser obtida por:

Collections.synchronizedMap(myMap);

Mas, para implementar corretamente essa lógica, você precisa de sincronização adicional do formulário:

synchronized(myMap) {
    if (!myMap.containsKey("tomato"))
        myMap.put("tomato", "red");
}

Mesmo a iteração sobre Hashtableas entradas de uma (ou uma HashMapobtida por Collections.synchronizedMap) não é segura para threads, a menos que você também proteja oMap sejam modificadas por meio de sincronização adicional.

As implementações da ConcurrentMapinterface (por exemplo ConcurrentHashMap) resolvem parte disso, incluindo a semântica de verificação e ação segura do thread , como:

ConcurrentMap.putIfAbsent(key, value);
serg10
fonte
53
Observe também que, se um HashMap for modificado, os iteradores que apontam para ele serão invalidados.
22720 Chris K
3
Portanto, existe alguma diferença entre sincronizado (myMap) {...} e ConcurrentHashMap em termos de thread thread safe?
telebog
3
Verdade
Love Hasija
@Bhushan: Ele será lançado com base no melhor esforço, este não é um comportamento garantido: docs.oracle.com/javase/7/docs/api/java/util/HashMap.html
Matt Stephenson
Tendo estado no meio de uma equipe de desenvolvimento da JVM há vários anos, posso afirmar que a sincronização interna do Hashtable é pelo menos útil para apontar corretamente o dedo no código do cliente quando ele escreve código simultâneo desonesto. Recebemos várias reclamações de falhas no HashMap (e, portanto, "obviamente" um bug do JDK / JVM), quando a causa foi uma modificação simultânea.
Hot Licks
363

Hashtableé considerado código legado. Não há nada sobre Hashtableisso que não possa ser feito usando HashMapou derivações de HashMap, portanto, para o novo código, não vejo justificativa para voltar Hashtable.

aberrant80
fonte
101
Do Hashtable javadoc (ênfase adicionada): "A partir da plataforma Java 2 v1.2, essa classe foi adaptada para implementar a interface Map, tornando-a membro do Java Collections Framework ." No entanto, você está certo de que é um código legado. Todos os benefícios da sincronização podem ser obtidos com mais eficiência com Collections.synchronizedMap (HashMap). (Semelhante a Vector sendo uma versão legado de Collections.synchronizedList (ArrayList).)
Kip
15
@ aberrant80: infelizmente, você não tem escolha entre os dois e tem que usar Hashtable quando a programação para J2ME ...
pwes
6
esta resposta deve ser excluída. Ele contém informações incorretas e possui muitos upvotes.
precisa saber é o seguinte
@ anon58192932 É possível editar a pergunta para corrigi-la?
GC_ 14/10
1
Temos que chamar a atenção do pôster @ aberrant80 ou de um administrador sinalizando. A sinalização pode ajudar - tentará isso agora.
anon58192932
189

Essa pergunta é frequentemente feita em entrevista para verificar se o candidato entende o uso correto das classes de coleta e está ciente das soluções alternativas disponíveis.

  1. o HashMap classe é aproximadamente equivalente a Hashtable, exceto que não é sincronizada e permite nulos. ( HashMappermite valores nulos como chave e valor, enquanto Hashtablenão permitenull s).
  2. HashMap não garante que a ordem do mapa permaneça constante ao longo do tempo.
  3. HashMapnão está sincronizado enquanto Hashtableestá sincronizado.
  4. O iterador no HashMapé à prova de falhas, enquanto o enumerador do Hashtablenão é e lança ConcurrentModificationExceptionse qualquer outro Thread modificar o mapa estruturalmente, adicionando ou removendo qualquer elemento, exceto Iteratoro próprioremove() método. Mas esse não é um comportamento garantido e será feito pela JVM com o melhor esforço.

Nota sobre alguns termos importantes:

  1. Sincronizado significa que apenas um encadeamento pode modificar uma tabela de hash em um ponto do tempo. Basicamente, isso significa que qualquer thread antes de executar uma atualização em umHashtable terá que adquirir um bloqueio no objeto, enquanto outros aguardarão a liberação do bloqueio.
  2. O fail-safe é relevante no contexto dos iteradores. Se um iterador foi criado em um objeto de coleção e algum outro encadeamento tenta modificar o objeto de coleção "estruturalmente", uma exceção de modificação simultânea será lançada. É possível que outros threads invoquem o setmétodo, pois ele não modifica a coleção "estruturalmente". No entanto, se antes da chamadaset , a coleção foi modificada estruturalmente, IllegalArgumentExceptionserá lançada.
  3. Modificar estruturalmente significa excluir ou inserir um elemento que possa efetivamente alterar a estrutura do mapa.

HashMap pode ser sincronizado por

Map m = Collections.synchronizeMap(hashMap);

O mapa fornece visualizações de coleção em vez de suporte direto à iteração via objetos de enumeração. As visualizações de coleção aprimoram bastante a expressividade da interface, conforme discutido mais adiante nesta seção. O mapa permite iterar sobre chaves, valores ou pares de valores-chave; Hashtablenão fornece a terceira opção. O mapa fornece uma maneira segura de remover entradas no meio da iteração; Hashtablenao fiz. Por fim, o Map corrige uma pequena deficiência na Hashtableinterface. Hashtablepossui um método chamado contains, que retorna true se o Hashtablecontém um determinado valor. Dado o nome, você esperaria que esse método retornasse true se Hashtablecontivesse uma chave determinada, porque a chave é o mecanismo de acesso primário para a Hashtable. A interface do mapa elimina essa fonte de confusão renomeando o método containsValue. Além disso, isso melhora a consistência da interface - containsValueparalelos containsKey.

A interface do mapa

sravan
fonte
19
Esta resposta contém pelo menos duas imprecisões factuais significativas. Certamente NÃO merece tantos votos positivos.
Stephen C
58
1) Os iteradores do HashMap NÃO são à prova de falhas. Eles são à prova de falhas. Há uma enorme diferença de significado entre esses dois termos. 2) Não há setoperação em a HashMap. 3) A put(...)operação não será lançada IllegalArgumentExceptionse houver uma alteração anterior. 4) O comportamento de falha rápida de HashMap também ocorre se você alterar um mapeamento. 5) O comportamento à prova de falhas é garantido. (O que não é garantido é o comportamento de um HashTablese você fizer uma modificação concorrente o comportamento real é ... imprevisível..)
Stephen C
25
6) Hashtabletambém não garante que a ordem dos elementos do mapa seja estável ao longo do tempo. (Você está talvez confundindo Hashtablecom LinkedHashMap.)
Stephen C
4
Alguém mais realmente se preocupou com o fato de os alunos hoje em dia terem a idéia errada de que obter "versões sincronizadas" das coleções de alguma forma significa que você não precisa sincronizar externamente operações compostas? Meu exemplo favorito desse ser thing.set(thing.get() + 1);que, na maioria das vezes, pega novatos de surpresa como completamente desprotegidos, especialmente se os métodos get()e set()forem sincronizados. Muitos deles estão esperando mágica.
Os iteradores no HashMap não são à prova de falhas
Abdul
130

HashMap: Uma implementação da Mapinterface que usa códigos de hash para indexar uma matriz. Hashtable: Oi, 1998 chamado. Eles querem a API de suas coleções de volta.

Sério, é melhor ficar longe de Hashtabletudo. Para aplicativos de thread único, você não precisa da sobrecarga extra de sincronização. Para aplicativos altamente simultâneos, a sincronização paranóica pode levar a fome, conflitos ou pausas desnecessárias na coleta de lixo. Como Tim Howland apontou, você pode usar ConcurrentHashMap.

Apocalisp
fonte
Isso realmente faz sentido. ConcurrentHashMaps oferece liberdade de sincronização e depuração é muito mais fácil.
prap19
1
Isso é específico para Java ou para toda a implementação do mapa de hash.
125

Lembre-se de que HashTableera uma classe herdada antes da introdução do Java Collections Framework (JCF) e posteriormente foi adaptado para implementar a Mapinterface. O mesmo foi Vectore Stack.

Portanto, sempre fique longe deles no novo código, pois sempre há uma alternativa melhor no JCF, como outros já haviam apontado.

Aqui está a folha de dicas da coleção Java que você achará útil. Observe que o bloco cinza contém a classe herdada HashTable, Vector e Stack.

insira a descrição da imagem aqui

pierrotlefou
fonte
72

Já existem muitas boas respostas. Estou adicionando alguns pontos novos e resumindo.

HashMape Hashtableambos são usados ​​para armazenar dados na forma de chave e valor . Ambos estão usando a técnica de hash para armazenar chaves exclusivas. Mas há muitas diferenças entre as classes HashMap e Hashtable que são fornecidas abaixo.

HashMap

  1. HashMapnão está sincronizado. Não é seguro para threads e não pode ser compartilhado entre muitos threads sem o código de sincronização adequado.
  2. HashMap permite uma chave nula e vários valores nulos.
  3. HashMap é uma nova classe introduzida no JDK 1.2.
  4. HashMap é rápido.
  5. Podemos fazer o HashMapcomo sincronizado chamando este código
    Map m = Collections.synchronizedMap(HashMap);
  6. HashMap é atravessado pelo Iterator.
  7. O iterador HashMapé à prova de falhas.
  8. HashMap herda a classe AbstractMap.

Hashtable

  1. Hashtableestá sincronizado. É seguro para threads e pode ser compartilhado com muitos threads.
  2. Hashtable não permite nenhuma chave ou valor nulo.
  3. Hashtable é uma classe herdada.
  4. Hashtable é lento.
  5. Hashtable é sincronizado internamente e não pode ser dessincronizado.
  6. Hashtable é percorrido pelo Enumerator e Iterator.
  7. O enumerador Hashtablenão é rápido.
  8. Hashtable herda a classe Dictionary.

Leitura adicional Qual é a diferença entre o HashMap e o Hashtable em Java?

insira a descrição da imagem aqui

roottraveller
fonte
Praticamente abordado nesta resposta (duplicado de) - stackoverflow.com/a/39785829/432903 .
prayagupd
Por que você diz ~ " Hashtable é uma classe herdada "? Onde está a documentação de suporte para isso.
IgorGanapolsky
2
@IgorGanapolsky você pode ler isto - stackoverflow.com/questions/21086307/…
roottraveller
Manter o HashMap é caro que o TreeMap. Porque o HashMap cria depósitos extras desnecessários.
Abdul
64

Além do que izb disse, HashMappermite valores nulos, enquanto Hashtableque não.

Observe também que Hashtableestende a Dictionaryclasse, que como o estado Javadocs , é obsoleta e foi substituída pela Mapinterface.

matt b
fonte
3
mas isso não torna obsoleto o HashTable?
Pacerier 1/11
O @Pacerier HashTable está obsoleto desde o Java 1.7.
Majid Ali Khan
62

Dê uma olhada neste gráfico. Ele fornece comparações entre diferentes estruturas de dados, juntamente com HashMape Hashtable. A comparação é precisa, clara e fácil de entender.

Matriz de coleção Java

Sujan
fonte
49

Hashtableé semelhante ao HashMape possui uma interface semelhante. É recomendável usar HashMap, a menos que você precise de suporte para aplicativos herdados ou precise de sincronização, pois os Hashtablesmétodos são sincronizados. Portanto, no seu caso, como você não é multi-threading, HashMapsé sua melhor aposta.

Miles D
fonte
36

Outra diferença importante entre hashtable e hashmap é que o Iterator no HashMap é à prova de falhas, enquanto o enumerador do Hashtable não é e lança ConcurrentModificationException se qualquer outro Thread modificar o mapa estruturalmente, adicionando ou removendo qualquer elemento, exceto o método remove () do próprio Iterator. Mas esse não é um comportamento garantido e será feito pela JVM com o melhor esforço. "

Minha fonte: http://javarevisited.blogspot.com/2010/10/difference-between-hashmap-and.html

Neerja
fonte
36

Além de todos os outros aspectos importantes já mencionados aqui, a API Collections (por exemplo, interface Map) está sendo modificada o tempo todo para estar em conformidade com as "últimas e melhores" adições às especificações Java.

Por exemplo, compare a iteração do Java 5 Map:

for (Elem elem : map.keys()) {
  elem.doSth();
}

versus a antiga abordagem Hashtable:

for (Enumeration en = htable.keys(); en.hasMoreElements(); ) {
  Elem elem = (Elem) en.nextElement();
  elem.doSth();
}

No Java 1.8, também nos é prometido ser capaz de construir e acessar o HashMaps, como nas boas e antigas linguagens de script:

Map<String,Integer> map = { "orange" : 12, "apples" : 15 };
map["apples"];

Atualização: Não, eles não chegarão em 1,8 ... :(

Os aprimoramentos da coleção do Project Coin serão no JDK8?

pwes
fonte
34

Hashtableestá sincronizado, enquanto HashMapnão está. Isso torna Hashtablemais lento que Hashmap.

Para aplicativos não encadeados, use, HashMappois eles são os mesmos em termos de funcionalidade.

izb
fonte
30
  • O HashTable é sincronizado. Se você o estiver usando em um único encadeamento, poderá usar o HashMap , que é uma versão não sincronizada. Objetos não sincronizados costumam ter um pouco mais de desempenho. A propósito, se vários threads acessam um HashMap simultaneamente e pelo menos um deles modifica o mapa estruturalmente, ele deve ser sincronizado externamente. Youn pode agrupar um mapa não sincronizado em um mapa sincronizado usando:

    Map m = Collections.synchronizedMap(new HashMap(...));
  • O HashTable pode conter apenas objetos não nulos como chave ou valor. O HashMap pode conter uma chave nula e valores nulos.

  • Os iteradores retornados pelo Map são rápidos, se o mapa for estruturalmente modificado a qualquer momento após a criação do iterador, de qualquer forma, exceto pelo método de remoção do próprio iterador, o iterador lançará a ConcurrentModificationException. Portanto, diante da modificação simultânea, o iterador falha de maneira rápida e limpa, em vez de arriscar um comportamento arbitrário e não determinístico em um tempo indeterminado no futuro. Enquanto as enumerações retornadas pelos métodos de chaves e elementos do Hashtable não são à prova de falhas.

  • HashTable e HashMap são membros do Java Collections Framework (desde a plataforma Java 2 v1.2, o HashTable foi adaptado para implementar a interface Map).

  • HashTable é considerado código legado, a documentação aconselha o uso do ConcurrentHashMap no lugar do Hashtable se uma implementação altamente simultânea segura por thread é desejada.

  • O HashMap não garante a ordem na qual os elementos são retornados. Para o HashTable, acho que é o mesmo, mas não tenho certeza, não encontro recursos que indiquem isso claramente.

alain.janinm
fonte
30

HashMape Hashtabletêm diferenças algorítmicas significativas também. Ninguém mencionou isso antes e é por isso que estou trazendo isso à tona. HashMapconstruirá uma tabela de hash com potência de dois tamanhos, aumentará dinamicamente para que você tenha no máximo cerca de oito elementos (colisões) em qualquer bucket e agitará os elementos muito bem para tipos de elementos gerais. No entanto, oHashtable implementação fornece um controle melhor e mais refinado sobre o hash, se você souber o que está fazendo, ou seja, você pode corrigir o tamanho da tabela usando, por exemplo, o número primo mais próximo ao tamanho do domínio de valores e isso resultará em melhor desempenho do que o HashMap, ou seja, menos colisões para alguns casos.

Separado das diferenças óbvias discutidas extensivamente nesta questão, vejo o Hashtable como um carro de "acionamento manual", onde você tem melhor controle sobre o hash e o HashMap como o equivalente de "acionamento automático" que geralmente apresenta bom desempenho.

SkyWalker
fonte
27

Com base nas informações aqui , eu recomendaria usar o HashMap. Eu acho que a maior vantagem é que o Java impedirá que você o modifique enquanto estiver iterando, a menos que você faça isso através do iterador.

pkaeding
fonte
5
Na verdade, não o impede, apenas o detecta e gera um erro.
Bart van Heukelom
1
Tenho certeza que ele lançará uma ConncurrentModificationException antes que a coleção subjacente seja modificada, embora eu possa estar errado.
pkaeding
Ele tentará detectar modificações simultâneas e lançar uma exceção. Mas se você estiver fazendo algo com threads, não poderá fazer promessas. Absolutamente tudo pode acontecer, incluindo quebra .
Chao
24

A Collection- às vezes chamado de contêiner - é simplesmente um objeto que agrupa vários elementos em uma única unidade. Collections 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.2e 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 Entryobjeto. A coleção de entradas é referida pelo objeto de HashMape 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.2Hashtable é 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 " hashcollision", 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).

Hash Map & Hashtable

« Modificação estrutural em caso de colisão de hash

HashMap, Hashtableno 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 HashMapcó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 = 8converta a lista vinculada de entradas em uma árvore balanceada, ao remover entradas menoresTREEIFY_THRESHOLD e no máximo UNTREEIFY_THRESHOLD = 6reconverterá 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 ConcurrentMapimplementaçã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.

  • HashMapEntryO 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, Hashtablemas 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

HashMappermite no máximo uma chave nula e qualquer número de valores nulos. Onde as Hashtablenã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 Hashtableem aplicativos multithread. Onde como HashMapnão é sincronizado internamente. Portanto, não é seguro usar HashMapem aplicativos multithread sem sincronização externa. Você pode sincronizar externamente HashMapusando o Collections.synchronizedMap()método

« Desempenho

Como Hashtableé sincronizado internamente, isso torna Hashtableum pouco mais lento que o HashMap.


@Vejo

Yash
fonte
18

Para aplicativos encadeados, muitas vezes você pode se safar do ConcurrentHashMap - depende dos seus requisitos de desempenho.

Tim Howland
fonte
17

1. Hashmape HashTablechave e valor da loja.

2. Hashmappode armazenar uma chave como null. Hashtablenão pode armazenar null.

3. HashMapnão está sincronizado, mas Hashtableestá sincronizado.

4. HashMappode ser sincronizado comCollection.SyncronizedMap(map)

Map hashmap = new HashMap();

Map map = Collections.SyncronizedMap(hashmap);
Rahul Tripathi
fonte
16

Além das diferenças já mencionadas, deve-se notar que, desde o Java 8, HashMapsubstitui dinamicamente os Nós (lista vinculada) usados ​​em cada bucket por TreeNodes (árvore vermelho-preta), de modo que, mesmo se houver colisão de hash alta, o pior caso é quando a pesquisa é

O (log (n)) para HashMap Vs O (n) em Hashtable.

* A melhoria acima mencionada não tenha sido aplicado a Hashtableainda, mas apenas para HashMap, LinkedHashMape ConcurrentHashMap.

FYI, atualmente,

  • TREEIFY_THRESHOLD = 8 : se um bucket contiver mais de 8 nós, a lista vinculada será transformada em uma árvore balanceada.
  • UNTREEIFY_THRESHOLD = 6 : quando um depósito fica muito pequeno (devido à remoção ou redimensionamento), a árvore é convertida novamente na lista vinculada.
Kostas Chalkias
fonte
14

Existem 5 diferenciações básicas com HashTable e HashMaps.

  1. O Maps permite iterar e recuperar chaves, valores e ambos os pares de valores-chave, onde o HashTable não possui todo esse recurso.
  2. No Hashtable, existe uma função contains (), que é muito confusa de usar. Porque o significado de contém é um pouco divergente. Se isso significa contém chave ou contém valor? difícil de entender. A mesma coisa no Maps, temos as funções ContainsKey () e ContainsValue (), que são muito fáceis de entender.
  3. No hashmap, você pode remover o elemento enquanto itera, com segurança. onde, como não é possível, em hashtables.
  4. As HashTables são sincronizadas por padrão, portanto podem ser usadas com vários threads facilmente. Onde os HashMaps não são sincronizados por padrão, eles podem ser usados ​​apenas com um único encadeamento. Mas você ainda pode converter o HashMap em sincronizado usando a função synchronizedMap (Map m) da classe Collections util.
  5. O HashTable não permitirá chaves ou valores nulos. Onde, como HashMap, permite uma chave nula e vários valores nulos.
user1923551
fonte
13

Minha pequena contribuição:

  1. A primeira e mais significativa diferença entre Hashtablee HashMapé que, HashMapnão é segura para threads, enquanto Hashtableé uma coleção segura para threads.

  2. Segunda diferença importante entre Hashtablee HashMapé o desempenho, uma vez que HashMapnão é sincronizado, ele tem um desempenho melhor que Hashtable.

  3. A terceira diferença no Hashtablevs HashMapé que Hashtableé uma classe obsoleta e você deve estar usando ConcurrentHashMapno lugar do HashtableJava.

Shreyos Adikari
fonte
11

HashMap: é uma classe disponível no pacote java.util e é usada para armazenar o elemento no formato de chave e valor.

Hashtable: é uma classe herdada que está sendo reconhecida dentro da estrutura da coleção.

Ankit
fonte
Se assim for, deve estar nos comentários, não como resposta.
manikant gautam 16/10/19
10

HashTable é uma classe herdada no jdk que não deve mais ser usada. Substitua os usos dele por ConcurrentHashMap . Se você não precisa de segurança do segmento, o uso HashMap que não é threadsafe , mas mais rápido e usa menos memória.

jontejj
fonte
Porque eu pensei que as outras respostas, na época, não descartaram o HashTable, mas explicaram que era seguro para threads. A verdade é que, assim que vir o HashTable no código, você deve substituí-lo pelo ConcurrentHashMap sem pular uma batida. E se a segurança do encadeamento não for uma preocupação, o HashMap pode ser usado para melhorar um pouco o desempenho.
precisa saber é
10
  1. Hashtableestá sincronizado enquanto HashMapnão está.
  2. Outra diferença é que o iterador no HashMapé à prova de falhas, enquanto o enumerador do Hashtablenão é. Se você alterar o mapa durante a iteração, você saberá.
  3. HashMappermite valores nulos, enquanto Hashtablenão.
rajá
fonte
3
O iterador HashMap é à prova de falhas e não à prova de falhas. É por isso que temos o ConcurrentHashMap que permite modificações durante a iteração. Verifique esta publicação journaldev.com/122/…
Pankaj
9

HashMap e HashTable

  • Alguns pontos importantes sobre o HashMap e o HashTable. por favor leia os detalhes abaixo.

1) Hashtable e Hashmap implementam a interface java.util.Map 2) Hashmap e Hashtable são uma coleção baseada em hash. e trabalhando em hash. portanto, essas são semelhanças entre HashMap e HashTable.

  • Qual é a diferença entre HashMap e HashTable?

1) A primeira diferença é que o HashMap não é seguro para threads enquanto o HashTable é ThreadSafe
2) O HashMap é melhor em termos de desempenho porque não é seguro para threads. enquanto o desempenho do Hashtable não é melhor porque é seguro para threads. portanto, vários segmentos não podem acessar o Hashtable ao mesmo tempo.

JegsVala
fonte
2
Votação negativa, porque esta resposta não está correta em alguns aspectos. O Hashtable não implementa a interface Map, mas apenas estende a classe Dictionary, que é obsoleta.
Yannis Sermetziadis
8

Hashtable:

Hashtable é uma estrutura de dados que retém valores do par de valores-chave. Não permite nulo para as chaves e os valores. Você receberá um NullPointerExceptionse adicionar valor nulo. Está sincronizado. Por isso, vem com seu custo. Somente um thread pode acessar o HashTable em um determinado momento.

Exemplo :

import java.util.Map;
import java.util.Hashtable;

public class TestClass {

    public static void main(String args[ ]) {
    Map<Integer,String> states= new Hashtable<Integer,String>();
    states.put(1, "INDIA");
    states.put(2, "USA");

    states.put(3, null);    //will throw NullPointerEcxeption at runtime

    System.out.println(states.get(1));
    System.out.println(states.get(2));
//  System.out.println(states.get(3));

    }
}

HashMap:

O HashMap é como o Hashtable, mas também aceita o par de valores-chave. Permite nulo para as chaves e os valores. Seu desempenho é melhor do que HashTable, porque é unsynchronized.

Exemplo:

import java.util.HashMap;
import java.util.Map;

public class TestClass {

    public static void main(String args[ ]) {
    Map<Integer,String> states = new HashMap<Integer,String>();
    states.put(1, "INDIA");
    states.put(2, "USA");

    states.put(3, null);    // Okay
    states.put(null,"UK");

    System.out.println(states.get(1));
    System.out.println(states.get(2));
    System.out.println(states.get(3));

    }
}
IntelliJ Amiya
fonte
5

HashMapé emulado e, portanto, utilizável, GWT client codeenquanto que Hashtablenão é.

pong
fonte
Essa é uma descrição abrangente das diferenças entre as duas APIs?
IgorGanapolsky
Sim (sic!). É tudo o que os desenvolvedores da GWT precisam saber sobre isso.
pong
5

Tópico antigo e clássico, basta adicionar este blog útil que explica isso:

http://blog.manishchhabra.com/2012/08/the-5-main-differences-betwen-hashmap-and-hashtable/

Blog de Manish Chhabra

As 5 principais diferenças entre o HashMap e o Hashtable

O HashMap e o Hashtable implementam a interface java.util.Map, mas existem algumas diferenças que os desenvolvedores Java devem entender para escrever um código mais eficiente. A partir da plataforma Java 2 v1.2, a classe Hashtable foi adaptada para implementar a interface Map, tornando-a membro do Java Collections Framework.

  1. Uma das principais diferenças entre o HashMap e o Hashtable é que o HashMap não é sincronizado, enquanto o Hashtable é sincronizado, o que significa que o Hashtable é seguro para threads e pode ser compartilhado entre vários threads, mas o HashMap não pode ser compartilhado entre vários threads sem sincronização adequada. O Java 5 introduziu o ConcurrentHashMap, que é uma alternativa ao Hashtable e fornece melhor escalabilidade do que o Hashtable em Java. Sincronizado significa que apenas um encadeamento pode modificar uma tabela de hash em um determinado momento. Basicamente, isso significa que qualquer thread antes de executar uma atualização em uma hashtable terá que adquirir um bloqueio no objeto, enquanto outros aguardarão a liberação do bloqueio.

  2. A classe HashMap é aproximadamente equivalente a Hashtable, exceto pelo fato de permitir nulos. (O HashMap permite valores nulos como chave e valor, enquanto o Hashtable não permite nulos).

  3. A terceira diferença significativa entre o HashMap e o Hashtable é que o Iterator no HashMap é um iterador à prova de falhas, enquanto o enumerador do Hashtable não é e lança ConcurrentModificationException se qualquer outro Thread modificar o mapa estruturalmente, adicionando ou removendo qualquer elemento, exceto a remoção do próprio Iterator ( ). Mas esse não é um comportamento garantido e será feito pela JVM com o melhor esforço. Essa também é uma diferença importante entre enumeração e iterador em Java.

  4. Uma diferença mais notável entre o Hashtable e o HashMap é que, devido à segurança e sincronização do encadeamento, o Hashtable é muito mais lento que o HashMap se usado em ambiente de encadeamento único. Portanto, se você não precisa de sincronização e o HashMap é usado apenas por um thread, ele executa o Hashtable em Java.

  5. O HashMap não garante que a ordem do mapa permaneça constante ao longo do tempo.

Observe que o HashMap pode ser sincronizado por

Map m = Collections.synchronizedMap(hashMap);

Em resumo, existem diferenças significativas entre o Hashtable e o HashMap em Java, por exemplo, segurança e velocidade do encadeamento e com base no uso do Hashtable apenas se você precisar absolutamente de segurança do encadeamento, se estiver executando o Java 5, considere usar o ConcurrentHashMap em Java.

Noite0
fonte
ConcurrentHashMap não é sincronizado para leitura, enquanto Hashtable é. Portanto, se você tiver uma grande quantidade de operações de leitura acontecendo simultaneamente com gravações, um Hashtable o ajudará melhor se você se importar com a integridade dos dados.
IgorGanapolsky
5

HashMap e Hashtable são usados ​​para armazenar dados na forma de chave e valor. Ambos estão usando a técnica de hash para armazenar chaves exclusivas. No entanto, existem muitas diferenças entre as classes HashMap e Hashtable fornecidas abaixo.

insira a descrição da imagem aqui

DeC
fonte
Resumo visual agradável!
Nadjib Mami