我有两个集合,它们都包含相同类型的对象,并且每个集合都有大约40K个对象。
每个集合所包含的对象的代码基本上就像一个字典,只是我覆盖了等号和哈希函数:
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;
}
}
}
我用来比较集合并获得差异的代码只是一个使用PLinq的简单Linq查询。
ParallelQuery p1Coll = sourceColl.AsParallel();
ParallelQuery p2Coll = destColl.AsParallel();
List<object> diffs = p2Coll.Where(r => !p1Coll.Any(m => m.Equals(r))).ToList();
有人知道比较这么多对象的更快的方法吗?目前在四核计算机上大约需要40秒+/- 2秒。基于数据进行分组,然后并行比较每组数据,这样会更快吗?如果我先根据Name对数据进行分组,我将得到大约490个唯一对象,如果我先根据ID对数据进行分组,我将得到大约622个唯一对象。
您可以使用Except方法,该方法将为您提供p2Coll
中不属于p1Coll
的每个项目。
var diff = p2Coll.Except(p1Coll);
UPDATE(一些性能测试):
免责声明:
实际时间取决于多种因素(例如集合的内容,硬件,机器上运行的内容,哈希码冲突的数量等),这就是为什么我们有复杂性和大O符号(参见Daniel brckner评论)。
下面是在我4年的机器上运行10次的性能统计:
Median time for Any(): 6973,97658ms
Median time for Except(): 9,23025ms
我的测试源代码可以在gist上找到。
更新2:
如果你想从第一个集合和第二个集合中获得不同的项目,你必须对两个集合都执行Expect,并对结果执行Union:
var diff = p2Coll.Except(p1Coll).Union(p1Coll.Except(p2Coll));
相交
int[] id1 = { 44, 26, 92, 30, 71, 38 };
int[] id2 = { 39, 59, 83, 47, 26, 4, 30 };
IEnumerable<int> both = id1.Intersect(id2);
foreach (int id in both)
Console.WriteLine(id);
/*
This code produces the following output:
26
30
*/