首页 文章

为什么Dictionary优先于Hashtable?

提问于
浏览
1256

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

18 回答

  • 8

    在.NET中, Dictionary<,>HashTable 之间的区别主要在于前者是泛型类型,因此您可以从静态类型检查(和减少拳击)方面获得泛型的所有好处,但这并不像人们倾向于那么大从性能的角度考虑 - 虽然拳击有一定的记忆成本 .

  • 7

    人们说词典与哈希表相同 .

    这不一定是真的 . 哈希表是字典的实现 . 这是一个典型的,它可能是.NET中的默认值,但它不是唯一的定义 .

    您同样可以使用链表或搜索树来实现字典,它只是效率不高(对于某些效率指标) .

  • 5

    仅供参考:在.NET中, Hashtable 可供多个读取器线程和单个写入线程使用,但在 Dictionary 中,公共静态成员是线程安全的,但不保证任何实例成员都是线程安全的 .

    因此,我们不得不将所有字典改回 Hashtable .

  • 5

    Hashtable 是一个松散类型的数据结构,因此您可以将任何类型的键和值添加到 Hashtable . Dictionary 类是一个类型安全的 Hashtable 实现,键和值是强类型的 . 创建 Dictionary 实例时,必须为键和值指定数据类型 .

  • 1450

    我能想到的另一个区别是:

    我们不能将Dictionary <KT,VT>(泛型)与Web服务一起使用 . 原因是没有Web服务标准支持泛型标准 .

  • 165

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

    相比

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

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

    但是, Dictionary 在内部实现为 Hashtable ,因此从技术上讲它的工作方式相同 .

  • 14

    从.NET Framework 3.5开始,还有一个HashSet<T>,它提供了Dictionary<TKey, TValue>的所有优点,如果您只需要键而没有值 .

    因此,如果您使用 Dictionary<MyType, object> 并始终将值设置为 null 来模拟类型安全哈希表,您应该考虑切换到HashSet<T> .

  • 7

    MSDN上的Extensive Examination of Data Structures Using C#文章指出 collision resolution strategy 也存在差异:

    Hashtable类使用称为 rehashing 的技术 .

    Rehashing的工作方式如下:有一组哈希不同的函数,H1 ... Hn,当从哈希表中插入或检索项时,最初使用H1哈希函数 . 如果这导致碰撞,则尝试使用H2,如果需要,则转到Hn .

    字典使用称为 chaining 的技术 .

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

  • 63

    Dictionary<> 是泛型类型,因此它的类型安全 .

    您可以在HashTable中插入任何值类型,这有时会抛出异常 . 但 Dictionary<int> 只接受整数值,同样 Dictionary<string> 只接受字符串 .

    因此,最好使用 Dictionary<> 而不是 HashTable .

  • 29

    另一个重要的区别是Hashtable是线程安全的 . Hashtable内置多个读取器/单个写入器(MR / SW)线程安全,这意味着Hashtable允许一个编写器与多个读取器一起使用而无需锁定 .

    在Dictionary的情况下,没有线程安全;如果您需要线程安全,则必须实现自己的同步 .

    进一步阐述:

    Hashtable通过Synchronized属性提供一些线程安全性,该属性返回集合周围的线程安全包装器 . 包装器通过在每次添加或删除操作时锁定整个集合来工作 . 因此,尝试访问集合的每个线程必须等待轮到一个锁 . 这不可扩展,可能会导致大型集合的性能显着下降 . 此外,该设计并未完全免受竞争条件的影响 . 像List <T>,Dictionary <TKey,TValue>等.NET Framework 2.0集合类不提供任何线程同步;当在多个线程上同时添加或删除项时,用户代码必须提供所有同步

    如果您需要类型安全性以及线程安全性,请在.NET Framework中使用并发集合类 . 进一步阅读here .

    另一个区别是,当我们在Dictionary中添加多个条目时,将保留添加条目的顺序 . 当我们从Dictionary中检索项目时,我们将按照插入它们的相同顺序获取记录 . 而Hashtable不保留插入顺序 .

  • 12

    CollectionsGenerics 对于处理对象组很有用 . 在.NET中,所有集合对象都在 IEnumerable 接口下,而接口 ArrayList(Index-Value))HashTable(Key-Value) . 在.NET framework 2.0之后, ArrayListHashTableListDictionary 替换 . 现在, ArraylistHashTable 在现在的项目中不再使用了 .

    HashTableDictionary 之间存在差异, Dictionary 是通用的,因为 Hastable 不是Generic . 我们可以将任何类型的对象添加到 HashTable ,但在检索时我们需要将其强制转换为所需类型 . 所以,它不是类型安全的 . 但是对于 dictionary ,在声明自己时我们可以指定键和值的类型,因此在检索时不需要进行强制转换 .

    我们来看一个例子:

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

    Dictionary,

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

    Dictionary <<< >>> Hashtable 差异:

    • Generic <<< >>> Non-Generic

    • 需要 own thread synchronization <<< >>>通过 Synchronized() 方法提供 thread safe 版本

    • 枚举项目: KeyValuePair <<< >>>枚举项目: DictionaryEntry

    • 较新(> .NET 2.0 )<<< >>>较旧(自 .NET 1.0

    • System.Collections.Generic <<< >>>在 System.Collections

    • 请求不存在的密钥 throws exception <<< >>>请求不存在的密钥 returns null

    • 可能是一个位 faster for value types <<< >>> bit slower (需要装箱/拆箱)用于值类型

    Dictionary / Hashtable 相似之处:

    • 两者都在内部 hashtables ==根据密钥快速访问多项数据

    • 两者都需要 immutable and unique keys

    • 两个键需要自己的 GetHashCode() 方法

    Similar .NET集合(候选使用而不是Dictionary和Hashtable):

    • ConcurrentDictionary - thread safe (可以同时从多个线程安全地访问)

    • HybridDictionary - optimized performance (少数项目和许多项目)

    • OrderedDictionary - 值可以是 accessed via int index (按添加项目的顺序)

    • SortedDictionary - items automatically sorted

    • StringDictionary - 强类型和 optimized for strings

  • 81

    Dictionary:

    • 如果我们试图找到一个不存在的密钥,它会返回/抛出异常 .

    • 它比Hashtable更快,因为没有装箱和拆箱 .

    • 只有公共静态成员是线程安全的 .

    • Dictionary是一种泛型类型,这意味着我们可以将它与任何数据类型一起使用(创建时,必须为键和值指定数据类型) .

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

    • Dictionay是Hashtable的类型安全实现, KeysValues 是强类型的 .

    Hashtable:

    • 如果我们尝试查找不存在的密钥,则返回null .

    • 它比字典慢,因为它需要装箱和拆箱 .

    • Hashtable中的所有成员都是线程安全的,

    • Hashtable不是泛型类型,

    • Hashtable是松散类型的数据结构,我们可以添加任何类型的键和值 .

  • 21

    Hashtable对象由包含集合元素的存储桶组成 . 存储桶是Hashtable中的虚拟子元素组, which makes searching and retrieving easier and faster than in most collections .

    Dictionary类与Hashtable类具有相同的功能 . 特定类型的字典(除了Object) has better performance than a Hashtable 用于值类型,因为Hashtable的元素是Object类型,因此,如果存储或检索值类型,通常会发生装箱和取消装箱 .

    进一步阅读:Hashtable and Dictionary Collection Types

  • 14

    根据我使用.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;
    

    所以我们可以确定DictionaryBase在内部使用HashTable .

  • 5

    请注意,MSDN说:“Dictionary <(Of <(TKey,TValue>)>)类实现为 hash table ", not " Dictionary <(Of <(TKey,TValue>)>)类实现为 HashTable

    Dictionary不是作为HashTable实现的,而是按照哈希表的概念实现的 . 由于使用了泛型,实现与HashTable类无关,尽管内部Microsoft可能使用了相同的代码并用TKey和TValue替换了Object类型的符号 .

    在.NET 1.0中,Generics不存在;这是HashTable和ArrayList最初开始的地方 .

  • -1

    HashTable:

    键/值将在存储到堆中时转换为对象(装箱)类型 .

    在从堆读取时,需要将键/值转换为所需类型 .

    这些操作非常昂贵 . 我们需要尽可能避免装箱/拆箱 .

    Dictionary : HashTable的通用变体 .

    没有拳击/拆箱 . 无需转换 .

  • 581

    对于它的 Value ,一个字典 is (概念上)一个哈希表 .

    如果你的意思是“为什么我们使用 Dictionary<TKey, TValue> 类而不是 Hashtable 类?”,那么这是一个简单的答案: Dictionary<TKey, TValue> 是泛型类型, Hashtable 不是 . 这意味着您可以使用 Dictionary<TKey, TValue> 获得类型安全性,因为您可以't insert any random object into it, and you don' t必须转换您取出的值 .

    有趣的是,.NET Framework中的 Dictionary<TKey, TValue> 实现基于 Hashtable ,正如您在其源代码中的评论所述:

    通用词典是从Hashtable的源代码复制而来的

    Source

相关问题