首页 文章

C#集合集?

提问于
浏览
427

有谁知道在C#中是否有与Java的 Set 集合相当的好处?我知道你可以通过填充但忽略值来使用 DictionaryHashTable 来模仿集合,但这不是一种非常优雅的方式 .

10 回答

  • 109

    在CodePlex上查看PowerCollections . 除了Set和OrderedSet之外,它还有一些其他有用的集合类型,如Deque,MultiDictionary,Bag,OrderedBag,OrderedDictionary和OrderedMultiDictionary .

    对于更多的集合,还有C5 Generic Collection Library .

  • 2

    我在 Dictionary<T, object> 周围使用了一个包装器,在值中存储了空值 . 这使得O(1)在键上添加,查找和删除,并且所有意图和目的都像集合一样 .

  • 0

    If you're using .NET 4.0 or later:

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

  • -5

    正如其他人所提到的那样,.NET标准中似乎没有set set语义的set实现 .

    有关为什么 HashSet 并不总是需要作为集合实现,请参见this question .

    如果您有兴趣滚动自己的集合类,这里有一个简单的方法:

    public sealed class MathSet<T> : HashSet<T>, IEquatable<MathSet<T>>
    {
        public override int GetHashCode() => this.Select(elt => elt.GetHashCode()).Sum().GetHashCode();
    
        public bool Equals(MathSet<T> obj) => SetEquals(obj);
    
        public override bool Equals(object obj) => Equals(obj as MathSet<T>);
    
        public static bool operator ==(MathSet<T> a, MathSet<T> b) =>
            ReferenceEquals(a, null) ? ReferenceEquals(b, null) : a.Equals(b);
    
        public static bool operator !=(MathSet<T> a, MathSet<T> b) => !(a == b);
    }
    

    用法示例:

    var a = new MathSet<int> { 1, 2, 3 };
    var b = new MathSet<int> { 3, 2, 1 };
    
    var c = a.Equals(b);                        // true
    
    var d = new MathSet<MathSet<int>> { a, b }; // contains one element
    
    var e = a == b;                             // true
    
  • 16

    试试HashSet

    HashSet(Of T)类提供高性能的集合操作 . set是一个不包含重复元素的集合,其元素没有特定的顺序...... HashSet(Of T)对象的容量是对象可以容纳的元素数 . 当元素添加到对象时,HashSet(Of T)对象的容量会自动增加 . HashSet(Of T)类基于数学集的模型,并提供类似于访问Dictionary(Of TKey,TValue)或Hashtable集合的键的高性能集合操作 . 简单来说,HashSet(Of T)类可以被认为是没有值的Dictionary(Of TKey,TValue)集合 . HashSet(Of T)集合未排序,不能包含重复元素...

  • 14

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

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

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

  • 398

    如果您使用的是.NET 3.5,则可以使用HashSet<T> . 尽管如此,它仍然适用于集合 .

    Wintellect PowerCollections也可能有所帮助 .

  • 12

    The HashSet<T> data structure:

    Framework Framework Library的 HashSet<T> 数据结构是在.NET Framework 3.5中引入的 . 可在MSDN reference page for HashSet<T>找到其成员的完整列表 .

    HashSet<T> 或多或少是在mathematical set之后建模的,这意味着:

    • 它可能不包含重复值 .

    • 其元素没有特别的顺序;因此该类型不实现IList<T>接口,但更基本的ICollection<T> . 因此,散列集内的元素不能通过索引随机访问;它们只能通过枚举器进行迭代 .

    • 某些设定功能,例如 UnionIntersectionIsSubsetOfIsSupersetOf 可用 . 当使用多组时,这些可以派上用场 .

    HashSet<T>List<T> 之间的另一个区别是调用哈希集的 Add(item) 方法返回一个布尔值:如果项目已添加则返回 true ,否则返回 false (因为它已在集合中找到) .

    Why not List<T>?

    由于 HashSet<T> 只是一个唯一对象的集合,您可能想知道为什么它必须是一个数据结构 . 正常 List<T> 可以通过在添加之前检查列表中是否找到对象来具有相同的行为 .

    简短的回答是速度 . 随着更多元素的添加,搜索正常 List<T> 变得非常慢 . HashSet<T> 需要一种结构设计,以便快速搜索和插入速度 .

    Benchmarks:

    让我们比较 HashSet<T>List<T> 的性能速度 .

    每个试验包括向每个集合添加0到9,999的整数 . 但是,mod 25适用于每个整数 . Mod 25生成最大类型的项目25.由于添加了10,000个元素,因此强制发生400次冲突,使数据结构有机会使用其搜索算法 . 在10,000次试验后测量3次并取平均值 .

    不要过多关注测试的具体运行时间,因为它们依赖于我的硬件,但要看它们如何相互比较 .

    Average time [ms]
    ----------------------------
    HashSet<T>             2,290
    List<T>                5,505
    

    现在让我们创建元素对象而不是基本类型 . 我写了一个包含三个字段的快速 Person 类: NameLastNameID . 由于我没有包含任何比较对象的特定方法,因此将添加所有元素而不会发生冲突 . 这个时间1,000个 Person 个对象被添加到每个集合中进行一次试验 . 平均每组3次1,000次试验的总次数 .

    Average time [ms]
    ----------------------------
    HashSet<Person>          201
    List<Person>           3,000
    

    正如您所看到的,运行时间的差异在使用对象时变得天文数字,这使得 HashSet<T> 具有优势 .

  • 82

    您可以在几个小时内实现自己的可行集实现 . 我必须这样做时使用了这个(抱歉,我没有方便的代码):http://java.sun.com/j2se/1.4.2/docs/api/java/util/Set.html

  • 11

    我用Iesi.Collections http://www.codeproject.com/KB/recipes/sets.aspx

    它在许多OSS项目中使用,我首先在NHibernate中遇到它

相关问题