C# HashSet 用法、Hashtable用法

本文详细介绍了.NET Framework中HashSet<T>与Hashtable的使用方法,包括创建、修改及遍历集合等操作,并提供了丰富的代码示例。

 HashSet 用法

.NET 3.5在System.Collections.Generic命名空间中包含一个新的集合类:HashSet<T>。这个集合类包含不重复项的无序列表。这种集合称为“集(set)”。集是一个保留字,所以该类有另一个名称HashSet<T>。这个名称很容易理解,因为这个集合基于散列值,插入元素的操作非常快,不需要像List<T>类那样重排集合。

HashSet<T>类提供的方法可以创建合集和交集。

创建HashSet:

 HashSet<string> hs = new HashSet<string>();

 HashSet<string> companyTeams = new HashSet<string>() { "Ferrari", "McLaren", "Toyota", "BMW", "Renault", "Honda" };

HashSet<T>改变集的值的方法:

Add(): 如果某元素不在集合中,Add()方法就把该元素添加到集合中。在其返回值Boolean中,返回元素是否添加的信息

eg:

 if (!companyTeams.Add("McLaren"))
            Console.WriteLine("McLaren was already in this set");

Clear():方法Clear()删除集合中的所有元素

eg: companyTeams.Clear();

Remove():Remove()方法删除指定的元素

eg: companyTeams.Remove("McLaren");

RemoveWhere(): RemoveWhere()方法需要一个Predicate<T>委托作为参数。删除满足谓词条件的所有元素

Predicate 可以委托给一个函数或者一个拉姆达表达式:

委托给拉姆达表达式:

eg:

 companyTeams.RemoveWhere(company => { if (company.Length > 5) { return true; } else { return false; } });

委托给一个函数:

eg:

 companyTeams.RemoveWhere(CheckLength);

public bool CheckLength(string company)
 {
            return company.Length > 5 ? true : false;
}

CopyTo(): CopyTo()把集合中的元素复制到一个数组中

eg:

string[] strArray = new string[companyTeams.Count];
companyTeams.CopyTo(strArray);
 foreach (string str in strArray)
{
        Console.WriteLine(str);
}

ExceptWith():ExceptWith()方法把一个集合作为参数,从集中删除该集合中的所有元素

eg:

 companyTeams.ExceptWith(privateTeams);
 foreach (var str in companyTeams)
 {
        Console.WriteLine(str);
 }

UnionWith():UnionWith()方法把传送为参数的集合中的所有元素添加到集中

eg:

 companyTeams.UnionWith(privateTeams);
 foreach (var str in companyTeams)
 {
         Console.WriteLine(str);
}


HashSet<T>仅返回集的信息、不修改元素的方法。

Contains():如果所传送的元素在集合中,方法Contains()就返回true

eg:

if (companyTeams.Contains("BMW"))
 {
          Console.WriteLine("companyTeams contains \"BMW\"");
}

IsSubsetOf():如果参数传送的集合是集的一个子集,方法IsSubsetOf()就返回true

eg:

if (traditionalTeams.IsSubsetOf(companyTeams))
 {
             Console.WriteLine("traditionalTeams is " + "subset of companyTeams");
 }

IsSupersetOf():如果参数传送的集合是集的一个超集,方法IsSupersetOf()就返回true

eg:
 if (companyTeams.IsSupersetOf(traditionalTeams))
 {
            Console.WriteLine("companyTeams is a superset of " + "traditionalTeams");
}

Overlaps():如果参数传送的集合中至少有一个元素与集中的元素相同,Overlaps()就返回true

eg:

traditionalTeams.Add("Williams");
 if (privateTeams.Overlaps(traditionalTeams))
{
            Console.WriteLine("At least one team is " + "the same with the traditional " + "and privateteams");
}

SetEquals():如果参数传送的集合和集包含相同的元素,方法SetEquals()就返回true


http://www.cnblogs.com/xiaopin/archive/2011/01/08/1930540.html


Hashtable用法:

一、哈希表(Hashtable)简述
     在.NET Framework中,Hashtable是System.Collections命名空间提供的一个容器,用于处理和表现类似key/value的键值对,其中key通常可用来快速查找,同时key是区分大小写;value用于存储对应于key的值。Hashtable中key/value键值对均为object类型,所以Hashtable可以支持任何类型的key/value键值对.

二、哈希表的简单操作
在哈希表中添加一个key/value键值对:HashtableObject.Add(key,value);
在哈希表中去除某个key/value键值对:HashtableObject.Remove(key);
从哈希表中移除所有元素:                HashtableObject.Clear();
判断哈希表是否包含特定键key:         HashtableObject.Contains(key);

Hashtable ht = new Hashtable(); //创建一个Hashtable实例
ht.Add("E", "e");//添加key/value键值对
ht.Add("A", "a");
ht.Add("C", "c");
ht.Add("B", "b");
string s = (string)ht["A"];
if (ht.Contains("E")) //判断哈希表是否包含特定键,其返回值为true或false
    Console.WriteLine("the E key:exist");
ht.Remove("C");//移除一个key/value键值对
Console.WriteLine(ht["A"]);//此处输出a
ht.Clear();//移除所有元素
Console.WriteLine(ht["A"]); //此处将不会有任何输出

三、遍历哈希表
遍历哈希表需要用到DictionaryEntry Object,代码如下:

foreach (DictionaryEntry de in ht) //ht为一个Hashtable实例
{
    Console.WriteLine(de.Key);//de.Key对应于key/value键值对key
    Console.WriteLine(de.Value);//de.Key对应于key/value键值对value
}

四、对哈希表进行排序
     对哈希表进行排序在这里的定义是对key/value键值对中的key按一定规则重新排列,但是实际上这个定义是不能实现的,因为我们无法直接在Hashtable进行对key进行重新排列,如果需要Hashtable提供某种规则的输出,可以采用一种变通的做法:

ArrayList akeys = new ArrayList(ht.Keys); //别忘了导入System.Collections
akeys.Sort(); //按字母顺序进行排序
foreach (string skey in akeys)
{
      Console.Write(skey + ":");
      Console.WriteLine(ht[skey]);//排序后输出
}

http://www.cnblogs.com/feisky/archive/2009/10/29/1591956.html


<think>好的,我现在要回答用户关于C#中IDictionary与Dictionary的用法区别的问题。首先,我需要回忆一下这两个类型的基本概念和它们在C#中的位置。 IDictionary是一个接口,属于System.Collections命名空间,而Dictionary<TKey, TValue>是具体的实现类,位于System.Collections.Generic命名空间中。用户可能想知道什么时候应该使用接口,什么时候用具体类,以及它们的主要差异在哪里。 接下来,我需要考虑它们的核心区别。接口IDictionary定义了一组必须实现的方法和属性,比如Add、Remove、Contains等,而Dictionary则是这个接口的一个具体实现,提供了基于哈希表的高效键值对存储。这里可能需要提到接口的抽象性带来的灵活性,比如可以替换不同的实现,比如SortedDictionary或者自定义的字典类,而Dictionary则是默认的哈希表实现。 然后,使用场景方面,当需要多态性或者编写通用代码时,使用IDictionary接口会更合适,比如方法参数或返回值声明为接口类型,提高代码的可扩展性。而Dictionary适用于明确知道需要哈希表特性的情况,比如快速查找、插入和删除操作。这里可能需要引用站内资料中的相关内容,比如引用[3]提到Dictionary和HashTable的区别,但用户的问题是关于IDictionary和Dictionary,所以需要调整。 另外,性能方面,虽然IDictionary接口本身不涉及性能,但具体实现如Dictionary的效率较高,特别是查找操作接近O(1)。而引用[2]提到遍历时Dictionary可能有较多的内存换页操作,但List更高效,不过这里讨论的是字典结构,所以可能不直接相关,但可以说明具体实现的性能特性需要考虑。 还要注意泛型和非泛型的区别。IDictionary有非泛型版本,而Dictionary<TKey, TValue>是泛型的,类型安全,避免了装箱拆箱。引用[5]中的泛型接口例子可以说明泛型的好处,比如IUnique<TId>接口,这里可以类比到IDictionary<TKey, TValue>。 用户可能还关心如何选择,比如在API设计中使用接口提高灵活性,而在内部实现中使用具体类确保性能。同时,需要提到其他实现IDictionary的类,比如HashTable(非泛型)、SortedDictionary等,以及它们的适用场景。 最后,要确保回答结构清晰,分点说明区别和场景,并引用相关的参考资料来支持观点。比如引用[4]提到在检索时使用HashSet代替List,但这里讨论的是字典结构,可能需要调整引用内容的位置,或者指出在不同集合类型间的选择依据。 总结:IDictionary是接口,Dictionary是实现;接口用于多态,具体类用于实例;性能上Dictionary高效;泛型与非泛型的区别;使用场景如API设计、性能需求等。</think>### C#中IDictionary与Dictionary的核心区别及使用场景 #### 一、类型性质差异 1. **IDictionary** - 是一个**泛型接口**(例如`IDictionary<TKey, TValue>`),定义键值对集合的基本操作规范,如`Add`、`Remove`、`ContainsKey`等[^1]。 - 支持多态性,允许通过接口调用不同实现类(如`Dictionary`、`SortedDictionary`)。 - 非泛型版本`IDictionary`(`System.Collections`命名空间)已逐渐被泛型版本替代[^3]。 2. **Dictionary** - 是**具体实现类**(`Dictionary<TKey, TValue>`),基于哈希表实现,提供高效的键值对存储与检索。 - 直接继承自`IDictionary<TKey, TValue>`,是标准哈希表结构,查找时间复杂度接近$O(1)$[^2]。 #### 二、核心差异对比 | 特性 | IDictionary<TKey, TValue> | Dictionary<TKey, TValue> | |---------------------|----------------------------------|-----------------------------------| | **类型** | 接口 | 具体实现类 | | **性能** | 依赖具体实现 | 哈希表结构,查找高效 | | **扩展性** | 支持多态(如替换为其他字典类型) | 固定实现 | | **线程安全** | 接口不保证 | 默认非线程安全,需手动同步 | | **泛型支持** | 是(类型安全) | 是(避免装箱拆箱) | #### 三、使用场景分析 1. **优先使用IDictionary的场景** - **API设计**:声明方法参数或返回值时,使用接口提高代码灵活性。 例如: ```csharp public void ProcessData(IDictionary<int, string> data) { ... } ``` - **多态需求**:需要兼容不同字典实现(如测试时替换为`SortedDictionary`)。 - **框架扩展**:自定义字典类时继承接口,保持与其他集合的兼容性[^1][^5]。 2. **优先使用Dictionary的场景** - **高频查询/插入**:需利用哈希表的$O(1)$时间复杂度优势[^2]。 - **明确键唯一性**:直接使用具体类简化代码,无需通过接口间接操作。 - **内存效率**:`Dictionary`对连续内存的优化优于非哈希结构的集合[^4]。 #### 四、性能对比示例 ```csharp // 使用Dictionary直接操作 var dict = new Dictionary<int, string>(); dict.TryGetValue(key, out value); // 接近O(1)的查找效率 // 通过IDictionary接口操作 IDictionary<int, string> idict = new Dictionary<int, string>(); idict.ContainsKey(key); // 实际调用Dictionary的实现 ``` #### 五、扩展说明 - **与其他字典类型的比较**: - `HashTable`:非泛型字典,存在装箱拆箱开销,已不推荐使用。 - `SortedDictionary`:基于红黑树实现,适合需要有序遍历的场景,但插入效率略低。 - **线程安全替代方案**: 若需线程安全,可使用`ConcurrentDictionary`(实现`IDictionary`接口)。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值