在大多数编程语言中,字典比哈希表更受欢迎。这背后的原因是什么?


当前回答

人们说字典和哈希表是一样的。

这不一定是真的。哈希表是实现字典的一种方法。这是一个典型的例子,它可能是.NET中Dictionary类中的默认例子,但根据定义,它不是唯一的例子。

你同样可以使用链接列表或搜索树来实现字典,但它并没有那么高效(对于一些高效的度量)。

其他回答

Hashtable对象由包含集合元素的桶组成。bucket是Hashtable中元素的虚拟子组,这使得搜索和检索比大多数集合更容易和更快。

Dictionary类具有与Hashtable类相同的功能。对于值类型,特定类型(而不是Object)的字典比Hashtable具有更好的性能,因为Hashtable的元素属于Object类型,因此,如果存储或检索值类型,通常会进行装箱和取消装箱。

进一步阅读:哈希表和字典集合类型

集合和泛型对于处理一组对象非常有用。在.NET中,所有集合对象都位于接口IEnumerable下,该接口又具有ArrayList(索引值)和HashTable(键值)。在.NET framework 2.0之后,ArrayList和HashTable被List和Dictionary取代。现在,Arraylist和HashTable在现在的项目中不再使用。

谈到HashTable和Dictionary之间的区别,Dictionary是泛型的,而Hastable不是泛型的。我们可以向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);
        }

    }
}

词典

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);
        }
    }
}

MSDN上的《使用C#对数据结构进行广泛检查》一文指出,冲突解决策略也存在差异:

Hashtable类使用一种称为rehashing的技术。

Rehashing的工作原理如下:有一组哈希不同的函数,H1。。。Hn,并且当从哈希中插入或检索项时表中,最初使用H1哈希函数。如果这导致如果需要,则尝试H2,然后继续到Hn。

字典使用了一种称为链接的技术。

通过重新散列,在发生冲突时,将重新计算哈希,并尝试与哈希对应的新槽。然而,通过链接,使用辅助数据结构来保存任何碰撞。具体来说,字典中的每个插槽都有一个数组映射到该存储桶的元素。如果发生碰撞冲突元素被添加到桶的列表中。

差异

Dictionary Hashtable
Generic Non-Generic
Needs own thread synchronization Offers thread safe version through Synchronized() method
Enumerated item: KeyValuePair Enumerated item: DictionaryEntry
Newer (> .NET 2.0) Older (since .NET 1.0)
is in System.Collections.Generic is in System.Collections
Request to non-existing key throws exception Request to non-existing key returns null
potentially a bit faster for value types bit slower (needs boxing/unboxing) for value types

相似之处:

两者都是内部哈希表==根据关键字快速访问许多项数据两者都需要不可变和唯一的密钥两者的键都需要自己的GetHashCode()方法

其他.NET集合:

(要使用的候选项,而不是字典和哈希表)

ConcurrentDictionary-线程安全(可以从多个线程同时安全访问)HybridDictionary-优化的性能(适用于少数项目,也适用于许多项目)OrderedDictionary-值可以通过int索引访问(按添加项的顺序)SortedDictionary-自动排序的项目StringDictionary-强类型并针对字符串进行了优化(现在不推荐使用Dictionary<string,string>)

因为Dictionary是一个泛型类(Dictionary<TKey,TValue>),所以访问其内容是类型安全的(即,不需要像Hashtable那样从Object转换)。

比较

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

to

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

然而,Dictionary在内部实现为哈希表,因此技术上它的工作方式相同。