HashSet <T>和List <T>有什么区别?
你能解释一下.NET中HashSet<T>
和List<T>
有什么不同?
也许你可以用一个例子来解释什么情况下HashSet<T>
应该比List<T>
更HashSet<T>
?
谢谢。
不像List <> …
-
HashSet是一个没有重复成员的列表。
-
因为HashSet被限制为仅包含唯一的条目,所以内部结构针对search进行了优化(与列表相比) – 它相当快
-
添加到HashSet将返回一个布尔值 – 如果由于已经存在的设置而导致添加失败,则返回false)。可以对Set:Union / Intersection / IsSubsetOf等进行math运算。
-
HashSet不执行仅IList ICollection
-
你不能使用HashSet的索引,只能使用枚举器。
如果您有兴趣执行Set操作,那么使用HashSet的主要原因是。
给定2组:hashSet1和hashSet2
//returns a list of distinct items in both sets HashSet set3 = set1.Union( set2 );
与使用LINQ的等效操作相比,飞行速度更快。 写起来也很贴心!
HashSet<T>
是一个类,用于为O(1)
查找包含(即,此集合是否包含特定对象,并快速告诉我答案)。
一个List<T>
是一个类,旨在为您提供一个具有O(1)
随机访问的集合,而不是dynamic增长的集合(想想dynamic数组)。 您可以在O(n)
时间testing遏制(除非该列表已sorting,那么您可以在O(log n)
时间进行二进制search)。
也许你可以用一个例子来解释一下,在什么情况下
HashSet<T>
应该优先于List<T>
当你想testingO(1)
遏制。
为了更精确地让我们用示例来演示,
在下面的例子中你不能使用HashSet。
HashSet<string> hashSet1 = new HashSet<string>(){"1","2","3"}; for (int i = 0; i < hashSet1.Count; i++) Console.WriteLine(hashSet1[i]);
hashSet1[i]
会产生一个错误:
不能用[]将索引应用于types为“System.Collections.Generic.HashSet”的expression式
你可以使用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有一些有用的function,如IntersectWith
, UnionWith
, IsProperSubsetOf
, ExceptWith
, 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
当你想要的时候使用一个List<T>
- 以一定的顺序存储项目的集合。
如果您知道所需项目的索引(而不是项目本身的值),则检索为O(1)
。 如果你不知道索引,find这个项目需要更多的时间, O(n)
为一个未分类的集合。
如果你想要使用Hashset<T>
- 快速查明某个对象是否包含在一个集合中。
如果你知道你想找的东西的名字,查找是O(1)
(这是'哈希'部分)。 它不像List<T>
那样维护一个顺序,你不能存储重复项(添加一个重复项没有效果,这就是'Set'部分)。
如果你想知道在拼字游戏中出现的单词是否是英文(或其他语言)中的有效单词,那么使用Hashset<T>
一个例子就是。 更好的办法是,如果你想build立一个networking服务供所有这样的游戏的在线版本使用。
一个List<T>
将是创build记分牌来追踪玩家分数的一个很好的数据结构。
列表是一个有序列表。 它是
- 由整数索引访问
- 可以包含重复
- 有一个可预测的顺序
HashSet是一个集合。 它:
- 可以阻止重复项目(请参阅添加(T) )
- 不保证集合内项目的顺序
- 具有您期望在集合上的操作, 例如 IntersectWith,IsProperSubsetOf,UnionWith。
当你想访问你的collections时,列表比较适合,就好像它是一个你可以附加,插入和删除项目的数组一样。 如果你想把你的集合看作是一个“包”,其顺序不重要,或者当你想用其他的集合比如IntersectWith或者UnionWith来操作时,HashSet是一个更好的select。
List是Type T对象的有序集合,与数组不同,您可以添加和删除条目。
您将使用一个列表,您要按照您存储它们的顺序引用成员,并且您正在通过位置而不是项目本身访问它们。
一个HashSet就像一个字典,该项目本身是关键以及值,sorting不保证。
你会使用一个HashSet来检查对象是否在集合中
列表不一定是唯一的,而哈希集是一个。
如果您决定将这些数据结构应用于数据驱动开发中的实际使用,HashSet在testing针对数据适配器源的复制方面非常有帮助,用于数据清理和迁移。
此外,如果使用DataAnnotations类,则可以实现类属性的Key逻辑,并有效地控制具有HashSet的自然索引(聚簇或不聚类),在List实现中这将非常困难。
使用列表的一个强有力的select是在视图模型上实现多种媒体的generics,比如向DropDownList Helper的MVC视图发送一个类的列表,以及通过WebApi作为JSON构造发送。 该列表允许典型的类集合逻辑,并且为更多“接口”类似的方法保持灵活性,以将单个视图模型计算到不同的介质。