C# 代码(`Hashtable` 和 `SortedList`)

一、Hashtable(哈希表)

1. 基本概念
  • 非泛型集合:存储键值对(object 类型),通过哈希算法实现快速查找。

  • 线程安全:默认非线程安全,可通过 Hashtable.Synchronized 创建线程安全版本。

  • 键的唯一性:键必须唯一,且不可为 null(值可为 null)。

2. 创建与初始化
// 创建空的 Hashtable
Hashtable hashtable = new Hashtable();
​
// 创建并初始化
Hashtable table = new Hashtable() {
    { 0, "这是0" },
    { "1", "这是1" },
    { true, "这是true" },
    { 'a', "aaaa" }
};
3. 常用属性与方法
操作代码示例说明
添加键值对table.Add(123, "123");添加键值对(键不存在时)。
通过键访问值string value = (string)table[true];通过键获取值(返回 object,需强制类型转换)。
通过键设置值table['a'] = "new value";修改已存在键对应的值。
判断键是否存在bool hasKey = table.ContainsKey(0);检查是否包含指定键。
判断值是否存在bool hasValue = table.ContainsValue("123");检查是否包含指定值。
删除键值对table.Remove(true);删除指定键对应的元素。
清空哈希表table.Clear();移除所有键值对。
获取元素数量int count = table.Count;返回哈希表中键值对的数量。
获取所有键ICollection keys = table.Keys;返回所有键的集合。
获取所有值ICollection values = table.Values;返回所有值的集合。
4. 遍历 Hashtable
// 遍历所有键值对
foreach (DictionaryEntry entry in table) {
    Console.WriteLine($"Key: {entry.Key}, Value: {entry.Value}");
}
​
// 单独遍历键或值
foreach (var key in table.Keys) {
    Console.WriteLine(key);
}
​
foreach (var value in table.Values) {
    Console.WriteLine(value);
}
5. 注意事项
  • 装箱拆箱:由于存储 object 类型,值类型(如 intbool)会发生装箱拆箱,影响性能。

  • 键的哈希码:键必须正确实现 GetHashCode()Equals() 方法,否则可能无法正确查找。

  • 无序性:遍历时元素顺序不确定,不保证与添加顺序一致。

二、SortedList(排序列表)

1. 基本概念
  • 非泛型集合:存储键值对,且按键自动排序(升序)。

  • 双重索引:支持通过键(如 sortedList[10])或索引位置(如 sortedList.GetByIndex(0))访问。

  • 内存优化:内部使用数组实现,适合静态数据(插入 / 删除频繁时性能较差)。

2. 创建与初始化
// 创建空的 SortedList
SortedList sortedList = new SortedList();
​
// 创建并初始化
SortedList list = new SortedList() {
    { 10, "这是10" },
    { 6, "这是6" },
    { 5, "这是5" },
    { 3, "这是3" }
};
// 注意:键必须可比较(实现 IComparable 接口),否则会报错(如混合数值和字符类型)
3. 常用属性与方法
操作代码示例说明
添加键值对list.Add(1, "这是1");添加键值对(键不存在时)。
通过键访问值string value = (string)list[10];通过键获取值(返回 object,需强制类型转换)。
通过索引访问值string value = (string)list.GetByIndex(0);通过索引位置获取值(索引按升序排列)。
通过索引访问键object key = list.GetKey(0);获取指定索引位置的键。
修改值list[10] = "新值";通过键修改对应的值。
删除键值对list.Remove(10);删除指定键对应的元素。
删除指定索引list.RemoveAt(0);删除指定索引位置的元素。
清空列表list.Clear();移除所有键值对。
获取元素数量int count = list.Count;返回列表中键值对的数量。
获取所有键ICollection keys = list.Keys;返回所有键的集合(按键升序排列)。
获取所有值ICollection values = list.Values;返回所有值的集合(按对应键的升序排列)。
4. 遍历 SortedList
// 遍历所有键值对(按键升序)
foreach (DictionaryEntry entry in list) {
    Console.WriteLine($"Key: {entry.Key}, Value: {entry.Value}");
}
​
// 通过索引遍历
for (int i = 0; i < list.Count; i++) {
    Console.WriteLine($"Index: {i}, Key: {list.GetKey(i)}, Value: {list.GetByIndex(i)}");
}
5. 注意事项
  • 键的可比较性:键必须实现 IComparable 接口(如 intstring 等),否则会抛出异常。

  • 性能特点:插入 / 删除操作较慢(O (n)),但查找效率高(O (log n))。

  • 索引与键的区别:索引从 0 开始,按升序排列的键顺序分配;而键是用户自定义的。

三、Hashtable 与 SortedList 的对比

特性HashtableSortedList
排序无序按键升序排序
数据结构哈希表(散列表)数组(双重索引)
查找效率O (1)(平均)O(log n)
插入 / 删除O (1)(平均)O (n)(需移动元素)
内存占用较高(需维护哈希表)较低(仅数组)
键类型要求需正确实现 GetHashCode()需实现 IComparable 接口
线程安全默认非线程安全默认非线程安全
推荐场景快速查找,无需排序需按键排序,且插入 / 删除较少

四、代码补充建议

1. Hashtable 补充
// 线程安全的 Hashtable
Hashtable syncTable = Hashtable.Synchronized(new Hashtable());
​
// 安全添加(避免键已存在的异常)
if (!table.ContainsKey(123)) {
    table.Add(123, "123");
}
​
// 安全获取值(避免键不存在的异常)
object value;
if (table.ContainsKey(0)) {
    value = table[0];
}
2. SortedList 补充
// 使用泛型版本 SortedList<TKey, TValue>(类型安全,无需装箱拆箱)
SortedList<int, string> genericList = new SortedList<int, string> {
    { 10, "这是10" },
    { 6, "这是6" }
};
​
// 检查键是否存在
if (genericList.ContainsKey(10)) {
    Console.WriteLine(genericList[10]);
}
​
// 添加或更新值
if (genericList.ContainsKey(10)) {
    genericList[10] = "更新的值";
} else {
    genericList.Add(10, "新值");
}

五、注意事项

  1. 泛型替代方案:推荐使用 Dictionary<TKey, TValue>(替代 Hashtable)和 SortedList<TKey, TValue>(替代非泛型 SortedList),以避免装箱拆箱。

  2. 性能权衡SortedList 在数据量大且插入 / 删除频繁时性能较差,可考虑使用 SortedDictionary<TKey, TValue>(基于红黑树,插入 / 删除效率为 O (log n))。

  3. 空引用检查:访问集合元素前建议检查 ContainsKey 或使用 TryGetValu

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

张謹礧

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值