En la mayoría de los lenguajes de programación, los diccionarios son preferibles a las tablas hash. ¿Cuáles son las razones detrás de eso?
c#
.net
vb.net
data-structures
Nakul Chaudhary
fuente
fuente
Dictionary
era una implementación deHashtable
.HashTable
. Cuando agregaron genéricos al idioma, llamaron la versión genéricaDictionary
. Ambas son tablas hash.Respuestas:
Por lo que vale, un Diccionario es (conceptualmente) una tabla hash.
Si quisiste decir "¿por qué usamos la
Dictionary<TKey, TValue>
clase en lugar de laHashtable
clase?", Entonces es una respuesta fácil:Dictionary<TKey, TValue>
es un tipo genérico,Hashtable
no lo es. Eso significa que obtienes seguridad de tipografíaDictionary<TKey, TValue>
, porque no puedes insertar ningún objeto aleatorio en él y no tienes que emitir los valores que extraes.Curiosamente, la
Dictionary<TKey, TValue>
implementación en .NET Framework se basa enHashtable
, como se puede ver en este comentario en su código fuente:Fuente
fuente
HashTable
(clase) comoDictionary
(clase) son tablas hash (concepto), pero aHashTable
no es aDictionary
, ni esDictionary
aHashTable
. Se usan de manera muy similar yDictionary<Object,Object>
pueden actuar de la misma manera sin tipo que aHashTable
, pero no comparten directamente ningún código (aunque es probable que las partes se implementen de manera muy similar).Dictionary
<<< >>>Hashtable
diferencias:Synchronized()
métodoKeyValuePair
enumerado : <<< >>> Artículo enumerado:DictionaryEntry
Dictionary
/Hashtable
similitudes:GetHashCode()
método propioColecciones .NET similares (candidatos para usar en lugar de Diccionario y Hashtable):
ConcurrentDictionary
- hilo seguro (se puede acceder de forma segura desde varios hilos al mismo tiempo)HybridDictionary
- rendimiento optimizado (para pocos artículos y también para muchos artículos)OrderedDictionary
- Se puede acceder a los valores a través del índice int (por orden en que se agregaron los elementos)SortedDictionary
- artículos ordenados automáticamenteStringDictionary
- fuertemente tipado y optimizado para cadenasfuente
StringDictionary
... por ciertoStringDictionary
no es lo mismo queDictionary<string, string>
cuando usas el constructor predeterminado.Porque
Dictionary
es una clase genérica (Dictionary<TKey, TValue>
), de modo que el acceso a su contenido es de tipo seguro (es decir, no es necesario emitir desdeObject
, como lo hace con aHashtable
).Comparar
a
Sin embargo,
Dictionary
se implementa internamente como tabla hash, por lo que técnicamente funciona de la misma manera.fuente
FYI: en .NET,
Hashtable
es seguro para subprocesos para su uso por múltiples subprocesos de lectura y un solo subproceso de escritura, mientras que enDictionary
los miembros estáticos públicos son seguros para subprocesos, pero no se garantiza que ningún miembro de instancia sea seguro para subprocesos.Hashtable
Debido a esto, tuvimos que cambiar todos nuestros diccionarios a .fuente
ConcurrentDictionary
clase que tiene todos los métodos públicos / protegidos implementados para ser seguros para subprocesos. Si no necesita admitir plataformas heredadas, esto le permitirá reemplazar elHashtable
código multiproceso: msdn.microsoft.com/en-us/library/dd287191.aspxEn .NET, la diferencia entre
Dictionary<,>
yHashTable
es principalmente que el primero es un tipo genérico, por lo que obtienes todos los beneficios de los genéricos en términos de verificación de tipo estático (y boxeo reducido, pero esto no es tan grande como la gente tiende a pensar) términos de rendimiento: sin embargo, hay un costo de memoria definido para el boxeo).fuente
La gente dice que un Diccionario es lo mismo que una tabla hash.
Esto no necesariamente es cierto. Una tabla hash es una forma de implementar un diccionario. Una típica en eso, y puede ser la predeterminada en .NET en la
Dictionary
clase, pero no es, por definición, la única.También podría implementar un diccionario utilizando una lista vinculada o un árbol de búsqueda, simplemente no sería tan eficiente (para algunas métricas de eficiente).
fuente
Dictionary<K,V>
.IDictionary<K,V>
podría ser cualquier cosa, aunque :)Collections
&Generics
son útiles para manejar grupos de objetos. En .NET, todos los objetos de colecciones vienen bajo la interfazIEnumerable
, que a su vez tieneArrayList(Index-Value))
&HashTable(Key-Value)
. Después de .NET Framework 2.0,ArrayList
&HashTable
fueron reemplazados porList
&Dictionary
. Ahora, losArraylist
&HashTable
ya no se utilizan en proyectos actuales.Llegar a la diferencia entre
HashTable
&Dictionary
,Dictionary
es genérico dondeHastable
no es genérico. Podemos agregar cualquier tipo de objetoHashTable
, pero al recuperarlo necesitamos convertirlo al tipo requerido. Por lo tanto, no es de tipo seguro. Perodictionary
, al declararse, podemos especificar el tipo de clave y valor, por lo que no es necesario emitir mientras se recupera.Veamos un ejemplo:
Tabla de picadillo
Diccionario,
fuente
Diccionario:
Devuelve / arroja Excepción si intentamos encontrar una clave que no existe.
Es más rápido que un Hashtable porque no hay boxeo ni unboxing.
Solo los miembros estáticos públicos son seguros para subprocesos.
El diccionario es un tipo genérico, lo que significa que podemos usarlo con cualquier tipo de datos (al crear, debe especificar los tipos de datos para claves y valores).
Ejemplo:
Dictionary<string, string> <NameOfDictionaryVar> = new Dictionary<string, string>();
Dictionay es una implementación segura de tipo de Hashtable,
Keys
yValues
está fuertemente tipada.Tabla de picadillo:
Devuelve nulo si intentamos encontrar una clave que no existe.
Es más lento que el diccionario porque requiere boxeo y unboxing.
Todos los miembros de un Hashtable son seguros para subprocesos,
Hashtable no es un tipo genérico,
Hashtable es una estructura de datos de tipo libre, podemos agregar claves y valores de cualquier tipo.
fuente
Dictionary.TryGetValue
El extenso examen de las estructuras de datos utilizando el artículo de C # en MSDN afirma que también hay una diferencia en la estrategia de resolución de colisiones :
La clase Hashtable utiliza una técnica denominada rehashing .
El Diccionario utiliza una técnica denominada encadenamiento .
fuente
Desde .NET Framework 3.5 también hay una
HashSet<T>
que proporciona todas las ventajas deDictionary<TKey, TValue>
si solo necesita las claves y ningún valor.Entonces, si usa ay
Dictionary<MyType, object>
siempre establece el valor paranull
simular la tabla hash de tipo seguro, tal vez debería considerar cambiar aHashSet<T>
.fuente
El
Hashtable
es una estructura de datos de tipo suelto, por lo que puede agregar claves y valores de cualquier tipo alHashtable
. LaDictionary
clase es unaHashtable
implementación de tipo seguro , y las claves y los valores están fuertemente tipados. Al crear unaDictionary
instancia, debe especificar los tipos de datos para la clave y el valor.fuente
Observe que MSDN dice: "La clase Dictionary <(Of <(TKey, TValue>)>) se implementa como una tabla hash ", no "La clase Dictionary <(Of <(TKey, TValue>)>) se implementa como HashTable "
El diccionario NO se implementa como HashTable, pero se implementa siguiendo el concepto de una tabla hash. La implementación no está relacionada con la clase HashTable debido al uso de genéricos, aunque internamente Microsoft podría haber usado el mismo código y reemplazado los símbolos de tipo Object con TKey y TValue.
En .NET 1.0 Generics no existía; Aquí es donde HashTable y ArrayList comenzaron originalmente.
fuente
Tabla de picadillo:
La clave / valor se convertirá en un tipo de objeto (boxeo) mientras se almacena en el montón.
La clave / valor debe convertirse al tipo deseado mientras se lee desde el montón.
Estas operaciones son muy costosas. Necesitamos evitar el boxeo / unboxing tanto como sea posible.
Diccionario: variante genérica de HashTable.
Sin boxeo / unboxing. No se requieren conversiones.
fuente
Un objeto Hashtable consta de depósitos que contienen los elementos de la colección. Un depósito es un subgrupo virtual de elementos dentro de Hashtable, que hace que la búsqueda y recuperación sea más fácil y rápida que en la mayoría de las colecciones .
La clase Diccionario tiene la misma funcionalidad que la clase Hashtable. Un diccionario de un tipo específico (que no sea Object) tiene un mejor rendimiento que un Hashtable para los tipos de valor porque los elementos de Hashtable son de tipo Object y, por lo tanto, el encajonamiento y el desempaquetado ocurren típicamente si se almacena o recupera un tipo de valor.
Para leer más: Tipos de colección de diccionario y hash
fuente
Otra diferencia importante es que Hashtable es seguro para subprocesos. Hashtable tiene seguridad de subproceso de lector múltiple / escritor único (MR / SW) incorporado, lo que significa que Hashtable permite UN escritor junto con múltiples lectores sin bloqueo.
En el caso de Dictionary no hay seguridad de hilo; Si necesita seguridad de subprocesos, debe implementar su propia sincronización.
Para elaborar más a fondo:
Si necesita seguridad de tipo y seguridad de subprocesos, use clases de colecciones concurrentes en .NET Framework. Lectura adicional aquí .
Una diferencia adicional es que cuando agregamos las entradas múltiples en el Diccionario, se mantiene el orden en que se agregan las entradas. Cuando recuperemos los elementos del Diccionario, obtendremos los registros en el mismo orden en que los insertamos. Mientras que Hashtable no conserva el orden de inserción.
fuente
Hashset
garantiza la seguridad de la rosca MR / SW en escenarios de uso que no implican eliminaciones . Creo que podría haber sido completamente seguro para MR / SW, pero manejar las eliminaciones de manera segura aumenta en gran medida el gasto de seguridad de MR / SW. Si bien el diseño deDictionary
podría haber ofrecido seguridad MR / SW a un costo mínimo en escenarios sin eliminación, creo que MS quería evitar tratar los escenarios sin eliminación como "especiales".Una diferencia más que puedo entender es:
No podemos usar Diccionario <KT, VT> (genéricos) con servicios web. La razón es que ningún estándar de servicio web admite el estándar genérico.
fuente
Dictionary<>
es un tipo genérico y, por lo tanto, es de tipo seguro.Puede insertar cualquier tipo de valor en HashTable y esto a veces puede generar una excepción. Pero
Dictionary<int>
solo aceptará valores enteros y de manera similarDictionary<string>
solo aceptará cadenas.Por lo tanto, es mejor usar en
Dictionary<>
lugar deHashTable
.fuente
No creo que esto sea necesariamente cierto, la mayoría de los idiomas tienen uno u otro, dependiendo de la terminología que prefieran .
En C #, sin embargo, la razón clara (para mí) es que C # HashTables y otros miembros del sistema. Los espacios de nombres de las colecciones son en gran parte obsoletos. Estaban presentes en c # V1.1. Han sido reemplazados de C # 2.0 por las clases genéricas en el espacio de nombres System.Collections.Generic.
fuente
Según lo que veo usando .NET Reflector :
Por lo tanto, podemos estar seguros de que DictionaryBase utiliza una HashTable internamente.
fuente