HashSet <t>与List <t>相同但具有唯一性吗?</t> </t>

时间:2012-03-19 20:44:30

标签: c# .net

我需要能够在集合中拥有唯一的项目。

我打算使用一个字典,所以我可以使用ContainsKey方法,但我认为这将是一种浪费,因为我不会使用Key / Value对的Value属性。

我遇到HashSet<T>看起来非常有希望。我在List<T>文档中找不到的唯一一件事就是HashSet<T>是无序的。我认为这很好,我认为这意味着它没有使用IEqualityComparer进行排序。只要添加项目的顺序位于相同的索引位置,我认为它就可以了,因为我必须进行重复检查,因此哈希集然后检查所有条目是顺序的。

比较这两种类型还有什么我错过的吗?

6 个答案:

答案 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)

你有点不对劲。 DictionaryHashSet都不会保留项目的顺序,这意味着您不能依赖项目索引。从理论上讲,您可以使用LINQ ElementAt()按索引访问项目,但两个集合都不保证保留订单。

.NET提供了一个OrderedDictionary类,但它不是通用的,所以在编译时你不会有类型安全性。无论如何,它允许按索引访问项目。

以下是通用实现的自定义实现:OrderedDictionary(of T): A generic implementation of IOrderedDictionary。关键点:它同时存在两个集合 - ListDictionary; List提供索引访问,Dictionary提供密钥快速访问。

答案 5 :(得分:1)

HashSet概念上是List个唯一值,但与List<T>不同,它实际上并不实现IList接口,而是实现ICollection 。 此外,它还有一系列特殊功能,例如:

IntersectionIsSubsetOfIsSupersetOfUnion, List<T>没有。{/ p>

这些功能当然在多个HasSet的操作中很方便。