Na maioria das linguagens de programação, os dicionários são preferidos às hashtables. Quais são as razões por trás disso?
c#
.net
vb.net
data-structures
Nakul Chaudhary
fonte
fonte
Dictionary
era uma implementação doHashtable
.HashTable
. Quando eles adicionaram genéricos ao idioma, eles chamaram a versão genéricaDictionary
. Ambas são tabelas de hash.Respostas:
Pelo que vale, um Dicionário é (conceitualmente) uma tabela de hash.
Se você quis dizer "por que usamos a
Dictionary<TKey, TValue>
classe em vez doHashtable
classe?", Então é uma resposta fácil:Dictionary<TKey, TValue>
é um tipo genérico,Hashtable
não é. Isso significa que você obtém segurança de digitaçãoDictionary<TKey, TValue>
, porque não pode inserir nenhum objeto aleatório nele e não precisa converter os valores que retirar.Curiosamente, o
Dictionary<TKey, TValue>
implementação no .NET Framework é baseada emHashtable
, como você pode ver neste comentário em seu código-fonte:Fonte
fonte
HashTable
(classe) eDictionary
(classe) são tabelas de hash (conceito), mas aHashTable
não é umDictionary
, nem é umDictionary
aHashTable
. Eles são usados de formas muito semelhantes eDictionary<Object,Object>
podem agir da mesma maneira não digitada que aHashTable
, mas não compartilham nenhum código diretamente (embora as partes provavelmente sejam implementadas de maneira muito semelhante).Dictionary
<<< >>>Hashtable
diferenças:Synchronized()
métodoKeyValuePair
<<< >>> Item enumerado:DictionaryEntry
Dictionary
/Hashtable
semelhanças:GetHashCode()
método próprioColeções .NET similares (candidatas a serem usadas em vez de Dictionary e Hashtable):
ConcurrentDictionary
- thread safe (pode ser acessado com segurança de vários threads simultaneamente)HybridDictionary
- desempenho otimizado (para poucos itens e também para muitos itens)OrderedDictionary
- valores podem ser acessados via índice int (por ordem em que os itens foram adicionados)SortedDictionary
- itens classificados automaticamenteStringDictionary
- fortemente tipado e otimizado para stringsfonte
StringDictionary
... btwStringDictionary
não é o mesmo deDictionary<string, string>
quando você usa o construtor padrão.Porque
Dictionary
é uma classe genérica (Dictionary<TKey, TValue>
), para que o acesso ao seu conteúdo seja seguro para o tipo (ou seja, você não precisa converter a partir deObject
, como faz com aHashtable
).Comparar
para
No entanto,
Dictionary
é implementado como tabela de hash internamente, portanto tecnicamente funciona da mesma maneira.fonte
FYI: No .NET, o
Hashtable
thread é seguro para uso por vários threads de leitor e um único thread de escrita, enquanto emDictionary
público membros estáticos são seguros, mas qualquer membro da instância não tem garantia de thread.Tivemos que mudar todos os nossos dicionários por
Hashtable
causa disso.fonte
ConcurrentDictionary
classe que possui todos os métodos públicos / protegidos implementados para serem seguros para threads. Se você não precisa de plataformas de suporte legado este iria deixá-lo substituir oHashtable
em código multithreaded: msdn.microsoft.com/en-us/library/dd287191.aspxNo .NET, a diferença entre
Dictionary<,>
eHashTable
é principalmente que o primeiro é um tipo genérico, então você obtém todos os benefícios dos genéricos em termos de verificação de tipo estático (e boxe reduzido, mas isso não é tão grande quanto as pessoas tendem a pensar) termos de desempenho - existe um custo definido de memória para o boxe).fonte
As pessoas estão dizendo que um dicionário é o mesmo que uma tabela de hash.
Isto não é necessariamente verdade. Uma tabela de hash é uma maneira de implementar um dicionário. Um exemplo disso, e pode ser o padrão no .NET na
Dictionary
classe, mas não é, por definição, o único.Você também pode implementar um dicionário usando uma lista vinculada ou uma árvore de pesquisa, mas não seria tão eficiente (para algumas métricas de eficiência).
fonte
Dictionary<K,V>
.IDictionary<K,V>
Poderia ser qualquer coisa, embora :)Collections
&Generics
são úteis para manipular grupos de objetos. No .NET, todos os objetos de coleçõesIEnumerable
ficam sob a interface , que por sua vez possuiArrayList(Index-Value))
&HashTable(Key-Value)
. Após o .NET framework 2.0,ArrayList
&HashTable
foram substituídos porList
&Dictionary
. Agora, oArraylist
&HashTable
não é mais usado nos projetos atuais.Chegando à diferença entre
HashTable
&Dictionary
,Dictionary
é genérico onde, comoHastable
não é genérico. Podemos adicionar qualquer tipo de objetoHashTable
, mas durante a recuperação, precisamos convertê-lo no tipo necessário. Portanto, não é do tipo seguro. Masdictionary
, enquanto se declara, podemos especificar o tipo de chave e valor, portanto, não há necessidade de converter durante a recuperação.Vejamos um exemplo:
HashTable
Dicionário,
fonte
Dicionário:
Ele retorna / lança Exception se tentarmos encontrar uma chave que não existe.
É mais rápido que um Hashtable porque não há boxe e unboxing.
Somente membros estáticos públicos são seguros para threads.
Dicionário é um tipo genérico, o que significa que podemos usá-lo com qualquer tipo de dados (ao criar, é necessário especificar os tipos de dados para chaves e valores).
Exemplo:
Dictionary<string, string> <NameOfDictionaryVar> = new Dictionary<string, string>();
Dictionay é uma implementação do Hashtable com segurança de tipo
Keys
eValues
é fortemente tipada.Hashtable:
Retorna nulo se tentarmos encontrar uma chave que não existe.
É mais lento que o dicionário porque requer boxe e unboxing.
Todos os membros em um Hashtable são seguros para threads,
Hashtable não é um tipo genérico,
Hashtable é uma estrutura de dados de tipo livre, podemos adicionar chaves e valores de qualquer tipo.
fonte
Dictionary.TryGetValue
O artigo Exame extensivo de estruturas de dados usando c # no MSDN afirma que também há uma diferença na estratégia de resolução de colisões :
A classe Hashtable usa uma técnica denominada rehashing .
O dicionário usa uma técnica chamada encadeamento .
fonte
Desde o .NET Framework 3.5, também existe um
HashSet<T>
que fornece todos os prós doDictionary<TKey, TValue>
se você precisar apenas das chaves e sem valores.Portanto, se você usar ae
Dictionary<MyType, object>
sempre definir o valor paranull
simular a tabela de hash do tipo seguro, considere mudar para aHashSet<T>
.fonte
A
Hashtable
é uma estrutura de dados de tipo fraco, para que você possa adicionar chaves e valores de qualquer tipo aoHashtable
. ADictionary
classe é umaHashtable
implementação com segurança de tipo e as chaves e valores são fortemente digitados. Ao criar umaDictionary
instância, você deve especificar os tipos de dados para a chave e o valor.fonte
Observe que o MSDN diz: "A classe Dictionary <(Of <(TKey, TValue>)>) é implementada como uma tabela de hash ", não a "Dictionary <(Of <(Of <(TKey, TValue>)>)) a classe é implementada como uma HashTable "
O dicionário NÃO é implementado como uma HashTable, mas é implementado seguindo o conceito de uma tabela de hash. A implementação não está relacionada à classe HashTable por causa do uso de Genéricos, embora internamente a Microsoft possa ter usado o mesmo código e substituído os símbolos do tipo Object por TKey e TValue.
No .NET 1.0, os genéricos não existiam; é aqui que o HashTable e o ArrayList começaram originalmente.
fonte
HashTable:
A chave / valor será convertida em um tipo de objeto (boxe) durante o armazenamento no heap.
A chave / valor precisa ser convertida no tipo desejado durante a leitura da pilha.
Essas operações são muito caras. Precisamos evitar o boxe / unboxing, tanto quanto possível.
Dicionário: variante genérica do HashTable.
Sem boxe / unboxing. Não são necessárias conversões.
fonte
Um objeto Hashtable consiste em depósitos que contêm os elementos da coleção. Um bucket é um subgrupo virtual de elementos no Hashtable, o que facilita a pesquisa e a recuperação e a recuperação mais rápida do que na maioria das coleções .
A classe Dictionary tem a mesma funcionalidade que a classe Hashtable. Um dicionário de um tipo específico (que não seja Objeto) tem melhor desempenho que um Hashtable para tipos de valor porque os elementos do Hashtable são do tipo Object e, portanto, o boxe e o unboxing geralmente ocorrem se o armazenamento ou a recuperação de um tipo de valor.
Para leitura adicional: Hashtable e Tipos de coleção de dicionário
fonte
Outra diferença importante é que o Hashtable é seguro para threads. O Hashtable possui segurança de encadeamento integrada para vários leitores / gravador único (MR / SW), o que significa que o Hashtable permite UM gravador junto com vários leitores sem travar.
No caso do Dictionary, não há segurança de threads; se você precisar de segurança de encadeamento, deverá implementar sua própria sincronização.
Para elaborar mais:
Se você precisar de segurança de tipo e segurança de thread, use classes de coleções simultâneas no .NET Framework. Leia mais aqui .
Uma diferença adicional é que, quando adicionamos várias entradas no Dicionário, a ordem na qual as entradas são adicionadas é mantida. Quando recuperamos os itens do Dictionary, obtemos os registros na mesma ordem em que os inserimos. Enquanto o Hashtable não preserva o pedido de inserção.
fonte
Hashset
garantias de segurança de encadeamento MR / SW em cenários de uso que não envolvem exclusões . Eu acho que pode ter sido planejado para ser totalmente seguro para MR / SW, mas o manuseio de exclusões com segurança aumenta bastante as despesas com segurança de MR / SW. Embora o design deDictionary
poderia oferecer segurança de MR / SW a um custo mínimo em cenários sem exclusão, acho que a MS queria evitar tratar os cenários sem exclusão como "especiais".Mais uma diferença que eu posso descobrir é:
Não podemos usar o Dicionário <KT, VT> (genéricos) com serviços da web. O motivo é que nenhum padrão de serviço da web suporta o padrão de genéricos.
fonte
Dictionary<>
é um tipo genérico e, portanto, é seguro.Você pode inserir qualquer tipo de valor no HashTable e, às vezes, isso pode gerar uma exceção. Mas
Dictionary<int>
só aceitará valores inteiros e da mesma formaDictionary<string>
somente aceitará strings.Então, é melhor usar em
Dictionary<>
vez deHashTable
.fonte
Eu não acho que isso seja necessariamente verdade, a maioria das línguas possui uma ou outra, dependendo da terminologia preferida .
No C #, no entanto, o motivo claro (para mim) é que o C # HashTables e outros membros do espaço para nome System.Collections são amplamente obsoletos. Eles estavam presentes no c # V1.1. Eles foram substituídos do C # 2.0 pelas classes Generic no espaço para nome System.Collections.Generic.
fonte
De acordo com o que vejo usando o .NET Reflector :
Portanto, podemos ter certeza de que o DictionaryBase usa uma HashTable internamente.
fonte