我需要能够在集合中拥有唯一的项目。
我打算使用一个字典,所以我可以使用ContainsKey方法,但我认为这将是一种浪费,因为我不会使用Key / Value对的Value属性。
我遇到HashSet<T>
看起来非常有希望。我在List<T>
文档中找不到的唯一一件事就是HashSet<T>
是无序的。我认为这很好,我认为这意味着它没有使用IEqualityComparer
进行排序。只要添加项目的顺序位于相同的索引位置,我认为它就可以了,因为我必须进行重复检查,因此哈希集然后检查所有条目是顺序的。
比较这两种类型还有什么我错过的吗?
答案 0 :(得分:20)
不,重要的是HashSet<T>
没有任何排序或索引的概念 - 列表在概念上有插槽0 .... n-1,而集合是“只是一个集合”。
无论如何我认为没关系,我认为这意味着它没有使用IEqualityComparer进行排序。
IEqualityComparer
不用于排序 - 它只讨论相等和哈希码。 {em>
只要添加项目的顺序位于相同的索引位置,我认为没问题。
没有索引位置,当你迭代HashSet<T>
时,无法保证你会按照添加它们的顺序取回它们。如果你甚至思考关于订购,SortedSet<T>
不是你想要的。
然后,所有这些也为HashSet<T>
的真实 - 你不应该对那里的排序作出任何假设。
答案 1 :(得分:9)
这是List<T>
看起来像的“图片”:
List: |a|b|r|t|i|p|c|y|z|...
Index: |0|1|2|3|4|5|6|7|8|...
List<T>
代表项目列表。您可以通过列表中的位置来引用项目。
这是HashSet<T>
看起来像的“图片”:
Set: |a|b|c| | | | | |i| | | | | | |p| |r| |t| | | | |y|z|
Bucket: |a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z|
HashSet<T>
代表一组唯一的项目。每个项目都有自己的“桶”。您可以通过其存储桶引用项目。项目所属的存储桶直接从项目计算。
使用HashSet
优于List
的一个优点是常量搜索。在List
中,项目可以位于List
中的任意位置,因此要查找它,您需要查看List
中的每个项目。在HashSet
中,任何给定项目只有一个可能的位置。因此,要搜索某个项目,您需要做的只是查看其存储桶。如果它在那里,它就在那里,如果它不存在,那就不是。
插图可能不是100%准确(为简单起见)。特别是HashSet
示例。
答案 2 :(得分:6)
没有。 HashSet
不允许通过索引访问,因为项目未订购。如您所怀疑的那样不意味着它们不是根据某些IEqualityComparer
排序的。这意味着它们不按照添加顺序存储在哈希集内。
因此,如果您需要订单保留或随机访问容器,HashSet
不适合您。
答案 3 :(得分:2)
听起来这就是你所追求的:
class UniqueList<T> : Collection<T>
{
protected override void InsertItem(int index, T item)
{
if (!base.Contains(item))
{
base.InsertItem(index, item);
}
else
{
// whatever
}
}
}
调用UniqueList.Add
会将一个项目添加到列表末尾,并且不会添加重复值。
答案 4 :(得分:1)
你有点不对劲。 Dictionary
和HashSet
都不会保留项目的顺序,这意味着您不能依赖项目索引。从理论上讲,您可以使用LINQ ElementAt()
按索引访问项目,但两个集合都不保证保留订单。
.NET提供了一个OrderedDictionary
类,但它不是通用的,所以在编译时你不会有类型安全性。无论如何,它允许按索引访问项目。
以下是通用实现的自定义实现:OrderedDictionary(of T): A generic implementation of IOrderedDictionary。关键点:它同时存在两个集合 - List
和Dictionary
; List提供索引访问,Dictionary
提供密钥快速访问。
答案 5 :(得分:1)
好HashSet
概念上是List
个唯一值,但与List<T>
不同,它实际上并不实现IList
接口,而是实现ICollection
。
此外,它还有一系列特殊功能,例如:
Intersection
,IsSubsetOf
,IsSupersetOf
,Union,
List<T>
没有。{/ p>
这些功能当然在多个HasSet
的操作中很方便。