HashSet <T>和List <T>有什么区别?

你能解释一下.NET中HashSet<T>List<T>有什么不同?

也许你可以用一个例子来解释什么情况下HashSet<T>应该比List<T>HashSet<T>

谢谢。

不像List <> …

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

  2. 因为HashSet被限制为仅包含唯一的条目,所以内部结构针对search进行了优化(与列表相比) – 它相当快

  3. 添加到HashSet将返回一个布尔值 – 如果由于已经存在的设置而导致添加失败,则返回false)。可以对Set:Union / Intersection / IsSubsetOf等进行math运算。

  4. HashSet不执行仅IList ICollection

  5. 你不能使用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,如IntersectWithUnionWithIsProperSubsetOfExceptWithSymmetricExceptWith

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构造发送。 该列表允许典型的类集合逻辑,并且为更多“接口”类似的方法保持灵活性,以将单个视图模型计算到不同的介质。