C# 哈希表及其示例

⚡ 智能摘要

C# 中的 Hashtable 是 System.Collections 命名空间中的一个集合,它将数据存储为键值对,其中每个唯一的键都映射到一个值,并且该键可以快速查找存储的值。

  • 📚 键值对: 哈希表为每个元素存储两个值,即键及其值,而不是像堆栈或数组列表那样只保存一个值。
  • 添加元素: Add 方法会将键和值一起插入,并且哈希表中的每个键都必须是唯一的。
  • 👀 包含键和包含值: 这些方法返回 true 或 false,因此您可以测试键或值是否已存在。
  • 🔁 读取数值: 使用 ICollection 的 Keys 属性或 DictionaryEntry 循环,可以依次读取每个存储的值。
  • 🛠️ 方法和属性: Remove、Clear、Count、Keys 和 Values 管理并检查哈希表的内容。
  • 🤖 人工智能辅助: GitHub Copilot 会生成 Hashtable 代码,而现代 C# 和 ML.NET 则倾向于使用通用的 Dictionary 来实现类型安全的键值数据。

C# 哈希表

C# 中的 Hashtable 是什么?

哈希表是一种用于存储键值项的特殊集合。因此,哈希表不会像堆栈、数组列表和队列那样只存储一个值,而是存储 2 个值。这两个值构成了哈希表的一个元素。

下面是哈希表值的一些示例。

{ "001" , ".Net" }
{ "002" , ".C#" }
{ "003" , "ASP.Net" }

上面我们有 3 个键值对。每个元素的键分别为 001、002 和 003。每个键值对的值是“。净“”、“C#”和“ASP.Net”。

让我们更详细地了解 Hashtable 集合可用的操作。

哈希表的声明

Hashtable 的声明如下所示。Hashtable 是在 Hashtable 数据类型的帮助下创建的。使用“new”关键字创建 Hashtable 对象。然后将该对象分配给变量 ht。

Hashtable ht = new Hashtable()

向哈希表添加元素

Add 方法用于将元素添加到 队列。该语句的一般语法如下

HashTable.add("key","value")

例如1:

请记住,哈希表的每个元素包含 2 个值,一个是键,另一个是值。

现在,让我们从代码层面看一下它是如何工作的。下面提到的所有代码都将写入我们的控制台应用程序。

代码将写入我们的 Program.cs 文件中。在下面的程序中,我们将编写代码来查看如何使用上述方法。

现在,在我们的示例中,我们仅了解如何创建哈希表、向哈希表添加元素并相应地显示它们。

C# 中的哈希表

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DemoApplication
{
 class Program
 {
  static void Main(string[] args)
  {
   Hashtable ht = new Hashtable();
   ht.Add("001",".Net");
   ht.Add("002","C#");
   ht.Add("003","ASP.Net");

   ICollection keys = ht.Keys;

   foreach (String k in keys)
   {
    Console.WriteLine(ht[k]);
   }
    Console.ReadKey();
   }
 }
}

Code 解释:-

  1. 首先,我们使用关键字“New”使用 Hashtable 数据类型声明哈希表变量。该变量定义的名称是“ht”。
  2. 然后我们使用 Add 方法将元素添加到哈希表中。请记住,在向哈希表添加内容时,我们需要添加键和值元素。
  3. 没有直接的方法来显示哈希表的元素。
    • 为了显示哈希表,我们首先需要从哈希表中获取键列表(001、002 和 003)。
    • 这是通过 ICollection 接口完成的。这是一种特殊的数据类型,可用于存储哈希表集合的键。然后我们将哈希表集合的键分配给变量“keys”。
  4. 接下来对于每个键值,我们使用语句 ht[k] 获取哈希表中的关联值。

如果正确输入上述代码并运行程序,将显示以下输出。

输出:

C# 中的哈希表

让我们看看哈希表可用的更多方法。

包含密钥

此方法用于查看 Hashtable 中是否存在某个键。以下是此语句的一般语法。如果键存在,则该语句将返回 true,否则将返回值 false。

Hashtable.Containskey(key)

包含值

此方法用于查看 Hashtable 中是否存在某个值。以下是此语句的一般语法。如果该值存在,则该语句将返回 true,否则将返回 false。

Hashtable.ContainsValue(value)

例如2:

让我们修改一下 控制台应用 展示如何使用“Containskey”和“ContainsValue”方法。

C# 中的哈希表

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DemoApplication
{
 class Program
 {
  static void Main(string[] args)
  {
   Hashtable ht = new Hashtable();
   ht.Add("001",".Net");
   ht.Add("002","C#");
   ht.Add("003","ASP.Net");

   Console.WriteLine(ht.ContainsKey("001"));
   Console.WriteLine(ht.ContainsValue("C#"));
   Console.ReadKey();
   }
 }
}

Code 解释:-

  1. 首先,我们使用 ContainsKey 方法查看哈希表中是否存在该键。如果哈希表中存在该键,则此方法将返回 true。由于哈希表中确实存在该键,因此此方法应该返回 true。
  2. 然后我们使用 ContainsValue 方法查看哈希表中是否存在该值。此方法将返回“true”,因为哈希表中确实存在该值。

如果正确输入上述代码并运行程序,将显示以下输出。

输出:

C# 中的哈希表

从输出中,您可以清楚地看到搜索的键和值都存在于哈希表中。

如何在 C# 中遍历哈希表

以上示例通过 Keys 集合读取值,但遍历哈希表还有更简洁的方法。使用 foreach 循环遍历 DictionaryEntry 可以一次性获取每个元素的键和值,这是读取哈希表最常用的方法。

步骤1) 创建一个哈希表,并向其中添加三个键值对。

步骤2) 使用 DictionaryEntry 变量遍历哈希表,然后读取每个条目的 Key 和 Value 属性。

using System;
using System.Collections;

namespace DemoApplication
{
 class Program
 {
  static void Main(string[] args)
  {
   Hashtable ht = new Hashtable();
   ht.Add("101", "Java");
   ht.Add("102", "Python");
   ht.Add("103", "Kotlin");

   foreach (DictionaryEntry entry in ht)
   {
    Console.WriteLine(entry.Key + " - " + entry.Value);
   }
   Console.ReadKey();
  }
 }
}

Code 解释:-

  1. 创建一个名为 ht 的哈希表,并使用 Add 方法插入三个键值对。
  2. foreach 循环将每个元素分配给 DictionaryEntry,其 Key 和 Value 属性公开了键值对的两部分。

程序运行时,它会将每个键及其值打印出来,例如 101 – Java由于哈希表不保留插入顺序,键值对出现的顺序可能与添加顺序不同。要仅读取键,请遍历 Keys 集合;要仅读取值,请遍历 Values 集合。

C# 哈希表方法和属性

Hashtable 类公开了一组方法和属性,几乎涵盖了您需要的所有任务,从添加和删除键值对到检查成员关系和统计元素数量。下面列出了最常用的成员。

会员 类型 描述
添加(键, 值) 付款方式 插入一个新的键值对;键必须是唯一的。
删除(键) 付款方式 删除与指定键匹配的元素。
清除() 付款方式 从哈希表中移除所有键值对。
包含键(key) 付款方式 当给定的键存在时,返回 true。
包含值(值) 付款方式 当给定值存在时,返回 true。
计数 特性 获取已存储的键值对的数量。
Keys 特性 返回所有键的集合。
理念 特性 返回所有值的集合。

由于每个键都被哈希处理,ContainsKey 和索引器几乎可以在恒定时间内找到元素,这使得哈希表对于快速查找非常有用。

C# 中哈希表和字典的区别

哈希表和字典都存储键值对,并且都属于 C# 语言的范畴。 收藏重要的区别在于类型安全,而这一区别决定了你在编写新代码时应该选择哪一种。

  • 型式安全: 哈希表将每个键和值存储为一个对象,而字典则使用对象存储键和值。是通用的,所以编译器会检查你使用的类型。
  • 空间: Hashtable 位于 System.Collections 中,而 Dictionary 位于 System.Collections.Generic 中。
  • Boxing: 哈希表会将整数等值类型封装起来,但通用字典直接存储它们,从而避免了这种开销。
  • 性能: 字典通常速度更快,因为读取值时不需要从对象进行类型转换。
  • 螺纹安全: 哈希表提供 Sync为一个写者有多个读者的情况提供标准化的包装,而并发代码通常选择 ConcurrentDictionary。

对于任何新项目,通用字典都是推荐的选择,而非通用哈希表主要出现在较旧的代码中。

常见问题

Remove 方法会删除具有给定键的元素,并将 Count 减 1。如果键不存在,则不会执行任何操作,因此,当必须确保键存在时,请先调用 ContainsKey 方法。

不。哈希表中的每个键都必须是唯一的。如果使用已存在的键调用 Add 方法,则会抛出 ArgumentException 异常。但是,您可以将相同的值存储在多个不同的键下,而不会出现任何错误。

哈希表可以安全地支持一个写者拥有多个读者。对于多个写入线程,请使用哈希表进行封装。Sync可以采用 hronized,或者选择 System.Collections.Concurrent 中的 ConcurrentDictionary,它可以处理并发读写操作而无需外部锁。

通过键查找值平均而言时间复杂度接近恒定的 O(1),因为键会被哈希处理以找到其对应的桶。严重的哈希冲突会降低速度,但对于分布良好的键来说,这种情况很少发生。

值可以为空,但键不能为空。将空键传递给 Add 函数或索引器会抛出 ArgumentNullException 异常。每个键都必须是唯一的,并且在存储期间不应更改。

哈希表本身不保存顺序,因此无法直接排序。需要将其键复制到列表或 ArrayList 中,对该列表进行排序,然后按键读取值。SortedList 会自动保持其条目的顺序。

是的。GitHub Copilot 会根据简短的注释或方法名自动生成 Hashtable 声明、Add 调用和 DictionaryEntry 循环。它通常会建议使用通用的 Dictionary 类型,因为这是新建 C# 代码的推荐集合。

ML.NET 的训练数据流经类型化集合和 IDataView 管道,而不是哈希表。但是,基于哈希的键值映射仍然支持特征查找、词汇编码以及机器学习模型的缓存。

总结一下这篇文章: