C#集合框架中的Set集合是什么?

565

有没有人知道C#中与Java的Set集合相当好的等价物?我知道你可以使用DictionaryHashTable 来模拟一组,方法是填充但忽略值,但这不是非常优雅的方式。

7个回答

447
如果你正在使用.NET 3.5,你可以使用HashSet<T>。不过,确实.NET对集合的支持没有Java那么好。
另外,Wintellect PowerCollections也可能会有所帮助。

19
我怀疑在某些编程语言中,"Set"是关键字,这可能会引起问题。 - Jon Skeet
5
@Manish:不是这样的。请看《C# 3 规范》的 2.4.3 节。它只对属性具有特殊意义。 - Jon Skeet
35
称之为 HashSet 而不是 Set 的原因与 Java 相同——"Set" 描述的是一个接口,而 "HashSet" 描述的是一种实现方式,具体来说就是由哈希映射支持的 Set。这样,我们知道(或应该强烈期望)插入和访问应该需要 O(1) 的访问时间,而使用 "LinkedListSet" 会导致我们期望插入和访问需要 O(n) 的时间。 - David Souther
6
".NET在处理集合方面不如Java。"你的意思是什么?这个Set与Java的相比有什么不完美之处吗?" - Louis Rhys
40
@Louis:你在说哪个Set?Java有很多不同的Set实现用于各种情况。.NET在.NET 3.5中有一个HashSet,在.NET 4中有两个HashSet和SortedSet。我们不得不等到.NET 3.5才开始使用这个,这事实相当令人惊讶。 - Jon Skeet
显示剩余3条评论

186

尝试使用HashSet

HashSet(Of T)类提供高效的集合操作。一个集合是一个不包含重复元素的集合,其元素没有特定的顺序...

HashSet(Of T)对象的能力是对象可以容纳的元素数量。当元素添加到对象中时,HashSet(Of T)对象的容量会自动增加。

HashSet(Of T)类基于数学集合模型,并提供类似于访问Dictionary(Of TKey, TValue)Hashtable集合的高性能集合操作。简单来说,可以将HashSet(Of T)类视为没有值的Dictionary(Of TKey, TValue)集合。

HashSet(Of T)集合不是有序的,也不能包含重复元素...


10
不幸的是,HashSet 直到最近才被添加。如果你在旧版本的框架中工作,你将不得不继续使用你混淆的 Dictionary<> 或 Hashtable。 - Greg D

34

如果您正在使用.NET 4.0或更高版本:

如果您需要进行排序,请使用SortedSet<T>。否则,如果不需要排序,则使用HashSet<T>,因为它对于搜索和操作是O(1)的。而SortedSet<T>对于搜索和操作是O(log n)的。


16

13
我使用一个围绕着 Dictionary<T, object> 的包装器,将 null 存储在值中。这样可以在键上实现 O(1) 的添加、查找和删除操作,并且在所有情况下都像一个集合一样运作。

2
你的意思是它大致相当于std::unordered_set。std::set是有序的。例如,您可以快速找到范围的起点和终点,并从起点迭代到终点,按键顺序访问项目。SortedDictionary 大致 相当于std::set。 - doug65536

12
请看一下Power Collections。除了SetOrderedSet之外,它还有一些其他有用的集合类型,如Deque, MultiDictionary, Bag, OrderedBag, OrderedDictionaryOrderedMultiDictionary
如果需要更多集合,还有C5 Generic Collection Library

-7

我知道这是一个旧的线程,但我遇到了同样的问题,并发现HashSet非常不可靠,因为在给定相同的种子时,GetHashCode()返回不同的代码。所以,我想,为什么不只是使用List并隐藏添加方法,像这样

public class UniqueList<T> : List<T>
{
    public new void Add(T obj)
    {
        if(!Contains(obj))
        {
            base.Add(obj);
        }
    }
}

因为List仅使用Equals方法来确定相等性,所以您可以在T类型上定义Equals方法,以确保获得所需的结果。

14
不建议使用这种方法的原因是List.Contains的时间复杂度为O(n),这意味着你的Add方法现在也变成了O(n)的复杂度。假设内部集合不需要重新调整大小,对于ListHashMapAdd应该都是O(1)的复杂度。简而言之,这种方法虽然可行,但效率较低且有些巧妙。 - Richard Marskell - Drackir
8
如果你的对象没有返回适当的GetHashCode值,那么你就不应该将它们放入基于哈希的容器中。更好的方法是修复GetHashCode而不是使用效率较低的容器。 - bmm6o

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接