您能解释一下.NET HashSet<T>
和之间的区别List<T>
吗?
也许您可以举一个例子来说明在哪种情况下HashSet<T>
应优先选择List<T>
?
您能解释一下.NET HashSet<T>
和之间的区别List<T>
吗?
也许您可以举一个例子来说明在哪种情况下HashSet<T>
应优先选择List<T>
?
Answers:
与List <>不同...
HashSet是一个没有重复成员的列表。
由于HashSet被限制为仅包含唯一条目,因此内部结构针对搜索(与列表相比)进行了优化-速度更快
添加到HashSet中会返回一个布尔值-如果由于Set中已存在添加而导致添加失败,则返回false
可以对Set执行以下数学运算:Union / Intersection / IsSubsetOf等。
HashSet不实现IList仅ICollection
您不能将索引与HashSet一起使用,只能与枚举器一起使用。
使用HashSet的主要原因是,如果您对执行Set操作感兴趣。
给定2组:hashSet1和hashSet2
//returns a list of distinct items in both sets
HashSet set3 = set1.Union( set2 );
与使用LINQ的等效操作相比,它飞行得更好。写也很整洁!
Union
方法方面遇到问题。我曾经使用过UnionWith
。
更确切地说,让我们通过示例进行演示,
您不能像以下示例中那样使用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的有像一些有用的功能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)
。如果您不知道索引,O(n)
对于未排序的集合,找到该项目会花费更多时间。
使用Hashset<T>
时要:
如果您知道要查找的事物的名称,则查找为O(1)
(即“哈希”部分)。它不会像这样保持顺序,List<T>
并且您不能存储重复项(添加重复项无效,这是“设置”部分)。
例如,Hashset<T>
如果您想找出在Scrabble游戏中玩过的单词是否是英语(或其他语言)中的有效单词,则可以使用一个示例。如果您想构建一个供此类游戏在线版本的所有实例使用的Web服务,那就更好了。
A List<T>
将是一个很好的数据结构,用于创建计分板来跟踪玩家分数。
如果您决定将这些数据结构应用于数据驱动的开发中的实际使用情况,则HashSet对于根据数据适配器源测试复制以进行数据清理和迁移非常有帮助。
同样,如果使用DataAnnotations类,则可以在类属性上实现键逻辑,并使用HashSet有效地控制自然索引(是否聚集),这在List实现中非常困难。
使用列表的一个强大选择是在视图模型上为多种媒体实现泛型,例如将类列表发送到DropDownList Helper的MVC视图,以及通过WebApi作为JSON构造发送。该列表允许典型的类收集逻辑,并为使用类似“接口”的方法为不同媒介计算单个视图模型保留了灵活性。