¿Por qué se prefiere el diccionario a la tabla Hash?


En la mayoría de los lenguajes de programación, los diccionarios son preferibles a los hashtables. ¿Cuáles son las razones detrás de eso?

Author: Peter Mortensen, 2008-11-19

18 answers

Por si sirve de algo, un Diccionario es (conceptualmente) una tabla hash.

Si quisieras decir "¿por qué usamos la clase Dictionary<TKey, TValue> en lugar de la clase Hashtable?"hay una respuesta fácil: Dictionary<TKey, TValue> es un tipo genérico, Hashtable no lo es. Eso significa que obtiene seguridad de tipo con Dictionary<TKey, TValue>, porque no puede insertar ningún objeto aleatorio en él, y no tiene que emitir los valores que elimina.

Curiosamente, la implementación de Dictionary<TKey, TValue> en. NET Framework se basa en Hashtable, como puede ver en este comentario en su código fuente:

El diccionario genérico fue copiado de la fuente de Hashtable

Fuente

 1422
Author: Michael Madsen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-12-15 12:52:41

Dictionary >> Hashtable diferencias:

  • Genérico >> No Genérica
  • Necesita sincronización de subprocesos propia >> Ofrece thread safe versión a través de Synchronized() método
  • Enumerado elemento: KeyValuePair >> Enumerados elemento: DictionaryEntry
  • Más nuevo (>. NET 2.0) >> Más antiguo (desde . NET 1.0)
  • está en Sistema.Colecciones.Genérico >> está en el sistema .Colecciones
  • Solicitud a clave no existente lanza excepción >> Request to non-existing key devuelve null
  • potencialmente un poco más rápido para los tipos de valor >> bit slower (necesita boxear / unboxing) para tipos de valor

Dictionary / Hashtable similitudes:

  • Ambos son internamente hashtables = = acceso rápido a los datos de muchos elementos según la clave
  • Ambos necesitan llaves inmutables y únicas
  • Las claves de ambos necesitan poseer GetHashCode() método

Colecciones similares. NET (candidatos a usar en lugar de Diccionario y Hashtable):

  • ConcurrentDictionary - thread safe (se puede acceder de forma segura desde varios hilos simultáneamente)
  • HybridDictionary - rendimiento optimizado (para pocos elementos y también para muchos elementos)
  • OrderedDictionary - los valores pueden ser accedidos a través del índice int (por orden en el que se agregaron los elementos)
  • SortedDictionary - elementos ordenados automáticamente
  • StringDictionary - fuertemente escrito y optimizado para cadenas
 574
Author: Thetam,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-01-15 09:59:08

Porque Dictionary es una clase genérica ( Dictionary<TKey, TValue>), por lo que acceder a su contenido es seguro para el tipo (es decir, no necesita enviar desde Object, como lo hace con un Hashtable).

Comparar

var customers = new Dictionary<string, Customer>();
...
Customer customer = customers["Ali G"];

A

var customers = new Hashtable();
...
Customer customer = customers["Ali G"] as Customer;

Sin embargo, Dictionary se implementa como Hashtable dentro, por lo que técnicamente funciona de la misma manera.

 164
Author: gius,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-12-06 12:43:52

Para su información: En.NET, Hashtable es seguro para el uso de subprocesos de múltiples lectores y un solo subproceso de escritura, mientras que en Dictionary los miembros estáticos públicos son seguros para subprocesos, pero no se garantiza que los miembros de instancia sean seguros para subprocesos.

Tuvimos que cambiar todos nuestros diccionarios de nuevo a Hashtable debido a esto.

 81
Author: user38902,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-23 08:00:20

En.NET, la diferencia entre Dictionary<,> y HashTable es principalmente que el primero es un tipo genérico, por lo que obtiene todos los beneficios de los genéricos en términos de comprobación de tipo estático (y boxeo reducido, pero esto no es tan grande como la gente tiende a pensar en términos de rendimiento - hay un costo de memoria definido para el boxeo, sin embargo).

 63
Author: Marc Gravell,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-11-19 09:54:50

La gente dice que un diccionario es lo mismo que una tabla hash.

Esto no es necesariamente cierto. Una tabla hash es una implementación de un diccionario. Uno típico en eso, y puede ser el predeterminado en. NET, pero no es por definición el único.

Igualmente podría implementar un diccionario con una lista vinculada o un árbol de búsqueda, simplemente no sería tan eficiente (para alguna métrica de eficiente).

 28
Author: rix0rrr,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-03-09 12:19:56

Collections & Generics son útiles para manejar grupos de objetos. En. NET, todos los objetos collections vienen bajo la interfaz IEnumerable, que a su vez tiene ArrayList(Index-Value)) & HashTable(Key-Value). Después de. NET framework 2.0, ArrayList & HashTable fueron reemplazados por List & Dictionary. Ahora, el Arraylist & HashTable ya no se utilizan en proyectos de hoy en día.

Llegando a la diferencia entre HashTable & Dictionary, Dictionary es genérico donde as Hastable no es Genérico. Podemos añadir cualquier tipo de objeto a HashTable, pero mientras lo recuperamos necesitamos lanzarlo al tipo requerido. Por lo tanto, no es tipo seguro. Pero para dictionary, mientras se declara a sí mismo, podemos especificar el tipo de clave y valor, por lo que no hay necesidad de emitir mientras se recupera.

Veamos un ejemplo:

HashTable

class HashTableProgram
{
    static void Main(string[] args)
    {
        Hashtable ht = new Hashtable();
        ht.Add(1, "One");
        ht.Add(2, "Two");
        ht.Add(3, "Three");
        foreach (DictionaryEntry de in ht)
        {
            int Key = (int)de.Key; //Casting
            string value = de.Value.ToString(); //Casting
            Console.WriteLine(Key + " " + value);
        }

    }
}

Diccionario,

class DictionaryProgram
{
    static void Main(string[] args)
    {
        Dictionary<int, string> dt = new Dictionary<int, string>();
        dt.Add(1, "One");
        dt.Add(2, "Two");
        dt.Add(3, "Three");
        foreach (KeyValuePair<int, String> kv in dt)
        {
            Console.WriteLine(kv.Key + " " + kv.Value);
        }
    }
}
 21
Author: Sujit,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-23 08:14:45

Diccionario:

  • Devuelve / lanza una excepción si tratamos de encontrar una clave que no existe.

  • Es más rápido que un Hashtable porque no hay boxeo y 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, debemos especificar los tipos de datos tanto para las claves como para los valores).

    Ejemplo: Dictionary<string, string> <NameOfDictionaryVar> = new Dictionary<string, string>();

  • Dictionay es una implementación segura de tipos de Hashtable, Keys y Values están fuertemente tipeados.

Hashtable:

  • Devuelve null si intentamos encontrar una clave que no existe.

  • Es más lento que el diccionario porque requiere boxeo y unboxing.

  • Todos los miembros en una tabla Hash son thread safe,

  • Hashtable no es un tipo genérico,

  • Hashtable es estructura de datos de tipo suelto, podemos agregar claves y valores de cualquier tipo.

 14
Author: Altaf Patel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-06-25 05:23:40

Desde. NET Framework 3.5 también hay un HashSet<T> que proporciona todos los pros de la Dictionary<TKey, TValue> si solo necesita las claves y ningún valor.

Entonces, si usa un Dictionary<MyType, object> y siempre establece el valor en null para simular la tabla hash segura de tipo, tal vez debería considerar cambiar a la HashSet<T>.

 14
Author: Oliver,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-23 08:15:58

El Examen Exhaustivo de las Estructuras de Datos Utilizando C # el artículo sobre MSDN establece que también hay una diferencia en la estrategia de resolución de colisiones :

La clase Hashtable utiliza una técnica denominada rehashing.

Rehashing funciona de la siguiente manera: hay un conjunto de funciones hash diferentes, H1 ... H n, y al insertar o recuperar un elemento del hash tabla, inicialmente la H1 la función hash es utilizar. Si esto conduce a una colisión, H2 se intenta en su lugar, y en adelante hasta H n si es necesario.

El Diccionario utiliza una técnica conocida como encadenamiento.

Con rehashing, en caso de colisión se vuelve a calcular el hash, y se prueba la nueva ranura correspondiente a un hash. Con el encadenamiento, sin embargo, se utiliza una estructura de datos secundaria para mantener cualquier colisión. Específicamente, cada ranura en el Diccionario tiene una matriz de elementos que se asignan a ese cubo. En caso de colisión, el el elemento de colisión se antepone a la lista del cubo.

 12
Author: alexandrekow,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-11-18 11:35:50

El Hashtable es una estructura de datos de tipo suelto, por lo que puede agregar claves y valores de cualquier tipo a Hashtable. La clase Dictionary es una implementación segura de tipo Hashtable, y las claves y los valores están fuertemente tipeados. Al crear una instancia Dictionary, debe especificar los tipos de datos tanto para la clave como para el valor.

 9
Author: flesh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-09-14 05:19:47

Observe que MSDN dice: "Dictionary)>) class se implementa como una hash table ", no "Dictionary)>) class se implementa como una HashTable "

El diccionario NO se implementa como una tabla hash, 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 utilizado el mismo código y reemplazado los símbolos de tipo Objeto con TKey y TValue.

En.NET 1.0 los genéricos no existían; aquí es donde comenzaron originalmente la tabla HASH y ArrayList.

 8
Author: Brant,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-23 08:10:15

Un objeto Hashtable consiste en cubos que contienen los elementos de la colección. Un bucket es un subgrupo virtual de elementos dentro de la tabla Hash, que hace que la búsqueda y la recuperación sean más fáciles y rápidas que en la mayoría de las colecciones.

La clase Dictionary tiene la misma funcionalidad que la clase Hashtable. Un diccionario de un tipo específico (distinto de Object) tiene mejor rendimiento que un Hashtable para tipos de valor porque los elementos de Hashtable son de tipo Object y, por lo tanto, boxing y unboxing suelen ocurrir si se almacena o recupera un tipo de valor.

Para más información: Tipos de colección de Hashtables y Diccionarios

 7
Author: mparkuk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-11-12 10:51:13

HashTable:

La clave/valor se convertirá en un tipo de objeto (boxing) mientras se almacena en el montón.

La clave/valor debe convertirse al tipo deseado mientras lee desde el montón.

Estas operaciones son muy costosas. Tenemos que evitar el boxeo / unboxing tanto como sea posible.

Diccionario: Variante genérica de HashTable.

No boxeo/unboxing. No se requieren conversiones.

 7
Author: Siva Sankar Gorantla,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-23 08:19:25

Una diferencia más que puedo averiguar es:

No podemos usar el diccionario (genéricos) con servicios web. La razón es que ningún estándar de servicio web admite el estándar genérico.

 5
Author: Peter Mortensen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-23 08:05:50

Dictionary<> es un tipo genérico y por lo tanto es 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 similar Dictionary<string> solo aceptará cadenas.

Por lo tanto, es mejor usar Dictionary<> en lugar de HashTable.

 5
Author: Kishore Kumar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-23 08:12:51

Otra diferencia importante es que Hashtable es seguro para subprocesos. Hashtable tiene seguridad de hilo de lector múltiple/escritor único (MR/SW) incorporada, lo que significa que Hashtable permite UN escritor junto con varios lectores sin bloqueo.

En el caso del Diccionario no hay seguridad de hilo; si necesita seguridad de hilo debe implementar su propia sincronización.

Para profundizar:

Hashtable proporciona cierta seguridad de hilo a través de la propiedad Synchronized, que devuelve un envoltorio seguro para hilos alrededor de la colección. La envoltura funciona bloqueando toda la colección en cada operación de agregar o quitar. Por lo tanto, cada hilo que intenta acceder a la colección debe esperar a que su turno tome el bloqueo. Esto no es escalable y puede causar una degradación significativa del rendimiento para grandes colecciones. Además, el diseño no está completamente protegido de las condiciones de carrera.

Las clases de colección de.NET Framework 2.0 como List<T>, Dictionary<TKey, TValue>, etc. no proporcionar cualquier sincronización de subprocesos; el código de usuario debe proporcionar toda la sincronización cuando se agregan o eliminan elementos en múltiples subprocesos simultáneamente

Si necesita seguridad de tipo y seguridad de subprocesos, utilice clases de colecciones concurrentes en.NET Framework. Más información aquí.

Una diferencia adicional es que cuando agregamos las entradas múltiples en el diccionario, se mantiene el orden en el que se agregan las entradas. Cuando recuperamos los elementos del Diccionario que obtendremos los registros en el mismo orden en que los hemos insertado. Mientras que Hashtable no conserva el orden de inserción.

 5
Author: NullReference,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-23 08:18:33

De acuerdo con lo que veo usando . NET Reflector :

[Serializable, ComVisible(true)]
public abstract class DictionaryBase : IDictionary, ICollection, IEnumerable
{
    // Fields
    private Hashtable hashtable;

    // Methods
    protected DictionaryBase();
    public void Clear();
.
.
.
}
Take note of these lines
// Fields
private Hashtable hashtable;

Así que podemos estar seguros de que DictionaryBase utiliza una tabla HASH internamente.

 -1
Author: Peter Mortensen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-23 08:12:07