找出2个集合与40K对象的差异

Jos*_*ong 3 c# linq plinq

我有2个集合都包含相同类型的对象,并且两个集合每个都有大约40K对象.

每个集合包含的对象的代码基本上就像一个字典,除了我重写了equals和hash函数:

public class MyClass: IEquatable<MyClass>
{
    public int ID { get; set; }
    public string Name { get; set; }

    public override bool Equals(object obj)
    {
        return obj is MyClass && this.Equals((MyClass)obj);
    }

    public bool Equals(MyClass ot)
    {
        if (ReferenceEquals(this, ot))
        {
            return true;
        }

        return 
         ot.ID.Equals(this.ID) &&
         string.Equals(ot.Name, this.Name, StringComparison.OrdinalIgnoreCase); 
    }

    public override int GetHashCode()
    {
         unchecked
         {
             int result = this.ID.GetHashCode();
             result = (result * 397) ^ this.Name.GetSafeHashCode();
             return result;
         }
    }
}
Run Code Online (Sandbox Code Playgroud)

我用来比较集合并获得差异的代码只是使用PLinq的简单Linq查询.

ParallelQuery p1Coll = sourceColl.AsParallel();
ParallelQuery p2Coll = destColl.AsParallel();

List<object> diffs = p2Coll.Where(r => !p1Coll.Any(m => m.Equals(r))).ToList();
Run Code Online (Sandbox Code Playgroud)

有没有人知道比较这么多物体的更快方法?目前在四核计算机上花费大约40秒+/- 2秒.是否会根据数据进行一些分组,然后并行比较每组数据可能会更快?如果我首先根据名称对数据进行分组,我最终会得到大约490个唯一对象,如果我先按ID分组,那么我最终会得到大约622个唯一对象.

Evg*_*ich 15

您可以使用Except方法,它将为您提供p2Coll不在其中的每个项目p1Coll.

var diff = p2Coll.Except(p1Coll);
Run Code Online (Sandbox Code Playgroud)

更新(一些性能测试):

免责声明:

实际时间取决于多个因素(例如集合的内容,硬件,计算机上运行的内容,哈希码冲突的数量等),这就是为什么我们有复杂性和Big O表示法(参见DanielBrückner评论).

以下是我4岁机器上10次运行的性能统计数据:

Median time for Any(): 6973,97658ms
Median time for Except(): 9,23025ms
Run Code Online (Sandbox Code Playgroud)

我的测试的源代码可以在gist上找到.


更新2:

如果你想拥有不同于第一和第二收集不同的项目,你必须做的其实期待双方和联盟的结果:

var diff = p2Coll.Except(p1Coll).Union(p1Coll.Except(p2Coll));
Run Code Online (Sandbox Code Playgroud)

  • 这应该快得多 - 问题的解决方案是"O(m*n)",这个解决方案在内部构建一个哈希表,因此是"O(m + n)". (8认同)