2011-06-17 274 views
136

你能解释一下.NET中的HashSet<T>List<T>之间有什么区别?HashSet <T>和List <T>有什么区别?

也许你可以在什么情况下应该HashSet<T>List<T>首选的例子解释一下吗?

谢谢。

+19

关于该主题的一些阅读:[C#/ .NET基础知识:选择正确的收集类](http://geekswithblogs.net/BlackRabbitCoder/archive/2011/06/16/c.net-fundamentals-choosing-the -right-collection-class.aspx) –

+0

我建议你参考http://en.wikipedia.org/wiki/Hash_table和http://en.wikipedia.org/wiki/Dynamic_array上的维基百科文章。 – mquander

+0

有关性能相关内容,请参见[hashset-vs-list-performance](http:// stackoverflow。com/questions/150750/hashset-vs-list-performance) – nawfal

回答

181

不像名单<> ...

  1. HashSet的是一个没有重复成员列表。

  2. 因为一个HashSet被限制为只包含唯一入口,内部结构搜索(使用列表进行比较)进行了优化 - 这是相当快

  3. 添加到HashSet返回一个布尔 - 假的,如果除了失败是由于现有的设置 )可以针对一组执行数学组操作:联盟/交集/ IsSubsetOf等

  4. HashSet中没有实现IList只有ICollection的

  5. 你不能在HashSet中使用索引,只能使用枚举器。

使用HashSet的主要原因是如果您有兴趣执行Set操作。

鉴于2套:hashSet1和hashSet2

//returns a list of distinct items in both sets 
HashSet set3 = set1.Union(set2); 

苍蝇与使用LINQ的等效操作的比较。写起来也很贴心!

+0

IDK,我有'union'方法的问题。我用'UnionWith'代替。 – user

+2

+1“如果您有兴趣执行Set操作,则使用HashedSet的主要原因是。 – Lijo

+10

实际上,我更喜欢这个答案,指出HashSets适用于可以将您的收藏作为“袋子物品”处理的情况。设置操作不像遏制检查那么频繁。在任何时候你有一套独特的项目(例如代码),你需要检查遏制,一个HashSet是方便的。 – ThunderGr

48

A HashSet<T>是一个类,旨在为您提供O(1)查找遏制(即该集合是否包含特定对象,并快速告诉我答案)。

一个List<T>是设计,让您的集合与O(1)随机存取比可以动态增长(想想动态数组)的类。您可以在O(n)时间内测试遏制(除非列表已排序,那么您可以在O(log n)时间执行二进制搜索)。

Maybe you can explain with an example in what cases HashSet<T> should be prefered against List<T>

当您想测试遏制在O(1)

+0

除O(log n)列表排序外,毕竟,它比在未排序的列表中查找更快。 – Andrei

3

列表是类型T的对象的有序集合,与数组不同,您可以添加和删除条目。

您将使用一个列表,您想按照您存储它们的顺序引用成员,并且您正在通过位置而不是项目本身访问它们。

HashSet就像一个字典,该项目本身是关键以及价值,排序不保证。

要检查的对象是集合

+1

为了澄清,如果其他人乍看之下读错了 - 列表'保持一个顺序(即添加事物),但不会自动分类项目。你必须调用'.Sort'或者使用'SortedList'。 – drzaus

18

使用List<T>中,当你想你可以使用一个HashSet来:

  • 商店以一定的顺序项的集合。

如果您知道所需物品的索引(而不是物品本身的值),则检索为O(1)。如果您不知道索引,找到该项目需要更多时间,O(n)用于未分类的集合。

使用Hashset<T>当你想:如果某个对象包含在集合中

  • 很快发现。

如果你知道你想要找的东西的名字,查找是O(1)(这是“哈希”部分)。它不会保留像List<T>那样的顺序,并且您不能存储重复项(添加副本不起作用,这是“设置”部分)。

例如,何时使用Hashset<T>可能是因为您想了解拼字游戏中的单词是否是英语(或其他语言)中的有效单词。如果你想构建一个网络服务供所有这种游戏的在线版本使用,那么更好的办法是。

A List<T>将是一个很好的数据结构,用于创建记分牌来跟踪玩家的得分。

13

列表是有序列表。它是

  • 由整数索引
  • 访问可以包含重复
  • 具有可预知的顺序

HashSet的是一组。它:

  • 可以阻止重复的项目(见Add(T)
  • 不保证集
  • 内项目的订单,你会期望在一组,例如操作,IntersectWith,IsProperSubsetOf,UnionWith。

当您想要访问您的集合时,列表更加合适,就像它可以像您可以添加,插入和删除项目的数组一样。如果你想把你的集合看作是一个“包”,其顺序不重要,或者当你想用其他集合比较它时,HashSet是一个更好的选择,使用诸如IntersectWith或UnionWith之类的操作。

41

为了更加精确让有例子表明,

不能在下面的例子中使用的HashSet等。

HashSet<string> hashSet1 = new HashSet<string>(){"1","2","3"}; 
for (int i = 0; i < hashSet1.Count; i++) 
    Console.WriteLine(hashSet1[i]); 

hashSet1[i]会产生一个错误:

Cannot apply indexing with [] to an expression of type 'System.Collections.Generic.HashSet'

您可以使用foreach语句:

foreach (var item in hashSet1) 
    Console.WriteLine(item); 

,而列表可以让你做你无法复制的项目添加到HashSet的这个和 当你正在添加一个项目到HashSet时,你可以检查它是否包含该项目与否。

HashSet<string> hashSet1 = new HashSet<string>(){"1","2","3"}; 
if (hashSet1.Add("1")) 
    Console.WriteLine("'1' is successfully added to hashSet1!"); 
else 
    Console.WriteLine("'1' could not be added to hashSet1, because it contains '1'"); 

HashSet的具有像IntersectWithUnionWithIsProperSubsetOfExceptWith,一些有用的功能SymmetricExceptWith

IsProperSubsetOf

HashSet<string> hashSet1 = new HashSet<string>() { "1", "2", "3", "4" }; 
HashSet<string> hashSet2 = new HashSet<string>() { "2", "4", "6", "8" }; 
HashSet<string> hashSet3 = new HashSet<string>() { "1", "2", "3", "4", "5" }; 
if (hashSet1.IsProperSubsetOf(hashSet3)) 
    Console.WriteLine("hashSet3 contains all elements of hashSet1."); 
if (!hashSet1.IsProperSubsetOf(hashSet2)) 
    Console.WriteLine("hashSet2 does not contains all elements of hashSet1."); 

UnionWith

HashSet<string> hashSet1 = new HashSet<string>() { "3", "4" }; 
HashSet<string> hashSet2 = new HashSet<string>() { "2", "4", "6", "8" }; 
hashSet1.UnionWith(hashSet2); //hashSet1 -> 3, 2, 4, 6, 8 

IntersectWith

HashSet<string> hashSet1 = new HashSet<string>() { "3", "4", "8" }; 
HashSet<string> hashSet2 = new HashSet<string>() { "2", "4", "6", "8" } 
hashSet1.IntersectWith(hashSet2);//hashSet1 -> 4, 8 

ExceptWith

HashSet<string> hashSet1 = new HashSet<string>() { "1", "2", "3", "5", "6" }; 
HashSet<string> hashSet2 = new HashSet<string>() { "1", "2", "3", "4" }; 
hashSet1.ExceptWith(hashSet2);//hashSet1 -> 5, 6 

SymmetricExceptWith

HashSet<string> hashSet1 = new HashSet<string>() { "1", "2", "3", "5", "6" }; 
HashSet<string> hashSet2 = new HashSet<string>() { "1", "2", "3", "4" }; 
hashSet1.SymmetricExceptWith(hashSet2);//hashSet1 -> 4, 5, 6 

顺便说一句,订单不会保留HashSets。在这个例子中,我们添加元素“2”最后,但它是在第二顺序:

HashSet<string> hashSet1 = new HashSet<string>() { "3", "4", "8" }; 
hashSet1.Add("1"); // 3, 4, 8, 1 
hashSet1.Remove("4"); // 3, 8, 1 
hashSet1.Add("2"); // 3, 2 ,8, 1 
+3

+1作为说明性示例。帮助我了解闪存中的HashSet操作!例如 – pKami

+2

+1。初学者将更容易掌握。 – nawfal

0

如果您决定将这些数据结构在数据驱动的发展实际使用情况,HashSet的是在测试非常有帮助针对数据适配器源的复制,用于数据清理和迁移。另外,如果使用DataAnnotations类,则可以实现类属性的Key逻辑,并有效控制具有HashSet的自然索引(聚簇或不聚类),这在List实现中非常困难。

使用列表的一个强有力的选择是在视图模型上实现多种媒介的泛型,比如向DropDownList Helper的MVC视图发送一个类的列表,以及通过WebApi发送为JSON构造。该列表允许典型的类集合逻辑,并且为更多的“接口”类似的方法保持灵活性,以将单个视图模型计算到不同的介质。

相关问题