HashSet <t>和List <t>之间有什么区别?</t> </t>

时间:2011-06-17 20:56:38

标签: .net list hashset difference

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

也许您可以通过一个示例来解释HashSet<T>应该首选哪些List<T>

感谢。

8 个答案:

答案 0 :(得分:192)

与List&lt;&gt;不同...

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

  2. 由于HashSet被限制为仅包含唯一条目,因此内部结构已针对搜索进行了优化(与列表进行比较) - 速度相当快

  3. 添加到HashSet会返回一个布尔值 - 如果添加因Set中已存在而失败,则返回false 。)可以对Set:Union / Intersection / IsSubsetOf等执行数学集合运算。

  4. HashSet不实现仅IList ICollection

  5. 您不能将索引与HashSet一起使用,只能使用枚举数。

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

    给定2组:hashSet1和hashSet2

     //returns a list of distinct items in both sets
     HashSet set3 = set1.Union( set2 );
    
    与使用LINQ的等效操作相比,

    飞得很快。写作也更整洁!

答案 1 :(得分:49)

HashSet<T>是一个专门用于O(1)查找包含的类(即,此集合是否包含特定对象,并快速告诉我答案)。

List<T>是一个类,旨在为您提供一个O(1)随机访问的集合,而不是动态增长(想想动态数组)。您可以在O(n)时间内测试包含(除非对列表进行排序,然后您可以在O(log n)时间内进行二进制搜索。)

  

也许您可以通过一个示例来解释HashSet<T>应该优先考虑List<T>

如果您想在O(1)中测试遏制。

答案 2 :(得分:47)

更准确地说,举例说明,

您不能像以下示例中那样使用HashSet。

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

hashSet1[i]会产生错误:

  

无法将带有[]的索引应用于类型的表达式   'System.Collections.Generic.HashSet'

您可以使用foreach语句:

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

您无法将重复项添加到HashSet,而List允许您执行此操作 当您向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有一些有用的功能,如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

答案 3 :(得分:18)

在您想要的时候使用List<T>

  • 按特定顺序存储项目集合。

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

在您想要的时候使用Hashset<T>

  • 快速查明某个集合中是否包含某个对象。

如果您知道要查找的内容的名称,则查找为O(1)(这是“哈希”部分)。它不像List<T>那样保持排序,你不能存储重复项(添加副本没有效果,那就是'Set'部分)。

何时使用Hashset<T>的示例是,如果您想知道在Scrabble游戏中播放的单词是否是英语(或其他语言)中的有效单词。如果您想构建一个Web服务,以供这种游戏的在线版本的所有实例使用,那就更好了。

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

答案 4 :(得分:13)

列表是一个有序列表。它是

  • 由整数索引
  • 访问
  • 可以包含重复项
  • 有可预测的订单

HashSet是一个集合。它:

  • 可以阻止重复的项目(请参阅Add(T)
  • 不保证集合中项目的顺序
  • 您可以在集合上进行操作,例如,IntersectWith,IsProperSubsetOf,UnionWith。

当您想要访问集合时,列表更合适,就像它可以追加,插入和删除项目的数组一样。如果您希望将您的集合视为“包”中的顺序不重要的项目,或者您希望使用IntersectWith或UnionWith等操作将其与其他集进行比较,则HashSet是更好的选择。

答案 5 :(得分:3)

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

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

HashSet就像一个字典,项目本身就是关键和价值,订单无法保证。

您可以使用HashSet来检查对象是否在集合中

答案 6 :(得分:2)

列表不一定是唯一的,而hashset是一个。

答案 7 :(得分:0)

如果您决定将这些数据结构应用于数据驱动开发中的实际使用,则HashSet在测试针对数据适配器源的复制,数据清理和迁移方面非常有用。

此外,如果使用DataAnnotations类,可以在类属性上实现Key逻辑,并使用HashSet有效地控制自然索引(无论是否聚簇),这在List实现中非常困难。

使用列表的一个强大选项是在视图模型上实现多个媒体的泛型,例如将类列表发送到DropDownList Helper的MVC视图,以及通过WebApi作为JSON构造发送。该列表允许典型的类集合逻辑,并保持更多&#34;接口&#34;就像将单个视图模型计算到不同介质的方法一样。