具有自定义 EqualityComparer 的 C# Hashset.Contains 从不调用 GetHashCode()
C# Hashset.Contains with custom EqualityComparer never calls GetHashCode()
我的数据库中有一个非常大(数十万)的客户对象哈希集。然后我得到一个新导入的客户对象哈希集,并且必须检查每个新对象是否包含在现有哈希集中。性能很重要。
我不能使用默认的 Equalitycomparer,因为它只需要根据三个属性进行比较。此外,由于其他原因,我无法覆盖 Customer class 的 Equals 和 GetHashCode 函数。所以我的目标是自定义 EqualityComparer(我尝试实现 IEqualityComparer 或从 EqualityComparer 继承并覆盖,如下所示 - 两者都具有相同的最终结果)。
public class CustomerComparer : EqualityComparer<Customer>
{
public CustomerComparer(){ }
public override bool Equals(Customer x, Customer y)
{
return x != null &&
y != null &&
x.Name == y.Name &&
x.Description == y.Description &&
x.AdditionalInfo == y.AdditionalInfo
}
public override int GetHashCode(Customer obj)
{
var hashCode = -1885141022;
hashCode = hashCode * -1521134295 + EqualityComparer<string>.Default.GetHashCode(obj.Name);
hashCode = hashCode * -1521134295 + EqualityComparer<string>.Default.GetHashCode(obj.Description);
hashCode = hashCode * -1521134295 + EqualityComparer<string>.Default.GetHashCode(obj.AdditionalInfo);
return hashCode;
}
}
现在我的问题是:当我使用默认的 EqualityComparer 时,通常只调用 Customer 的 GetHashCode 方法,并且我的用例的性能非常好(1-2 秒)。当我使用自定义 EqualityComparer 时,从未调用 GetHashCode 方法,但始终调用 Equals 方法。我的用例的性能非常糟糕(数小时)。请参阅下面的代码:
public void FilterImportedCustomers(ISet<Customer> dataBase, IEnumerable<Customer> imported){
var equalityComparer = new CustomerComparer();
foreach (var obj in imported){
//great performance, always calls Customer.GetHashCode
if (!dataBase.Contains(obj){
//...
}
//awful performance, only calls CustomerComparer.AreEqual
if (!dataBase.Contains(obj, equalityComparer))
//...
}
}
}
有没有人知道我该如何解决这个问题?那太棒了,我真的一直在努力解决这个巨大的性能问题。
编辑:
我在初始化哈希集时通过我的 EuqalityComparer 解决了这个问题!通过使用采用 IEqualityComparer 的构造函数重载,因此 var database = new HashSet(new CustomerComparer())
谢谢大家!
我在初始化哈希集时通过传递我的 EqualityComparer 解决了这个问题!使用了采用 IEqualityComparer 的构造函数重载,因此 var database = new HashSet(new CustomerComparer())
感谢Lee和NetMage在我的原创下发表评论post。
我的数据库中有一个非常大(数十万)的客户对象哈希集。然后我得到一个新导入的客户对象哈希集,并且必须检查每个新对象是否包含在现有哈希集中。性能很重要。
我不能使用默认的 Equalitycomparer,因为它只需要根据三个属性进行比较。此外,由于其他原因,我无法覆盖 Customer class 的 Equals 和 GetHashCode 函数。所以我的目标是自定义 EqualityComparer(我尝试实现 IEqualityComparer 或从 EqualityComparer 继承并覆盖,如下所示 - 两者都具有相同的最终结果)。
public class CustomerComparer : EqualityComparer<Customer>
{
public CustomerComparer(){ }
public override bool Equals(Customer x, Customer y)
{
return x != null &&
y != null &&
x.Name == y.Name &&
x.Description == y.Description &&
x.AdditionalInfo == y.AdditionalInfo
}
public override int GetHashCode(Customer obj)
{
var hashCode = -1885141022;
hashCode = hashCode * -1521134295 + EqualityComparer<string>.Default.GetHashCode(obj.Name);
hashCode = hashCode * -1521134295 + EqualityComparer<string>.Default.GetHashCode(obj.Description);
hashCode = hashCode * -1521134295 + EqualityComparer<string>.Default.GetHashCode(obj.AdditionalInfo);
return hashCode;
}
}
现在我的问题是:当我使用默认的 EqualityComparer 时,通常只调用 Customer 的 GetHashCode 方法,并且我的用例的性能非常好(1-2 秒)。当我使用自定义 EqualityComparer 时,从未调用 GetHashCode 方法,但始终调用 Equals 方法。我的用例的性能非常糟糕(数小时)。请参阅下面的代码:
public void FilterImportedCustomers(ISet<Customer> dataBase, IEnumerable<Customer> imported){
var equalityComparer = new CustomerComparer();
foreach (var obj in imported){
//great performance, always calls Customer.GetHashCode
if (!dataBase.Contains(obj){
//...
}
//awful performance, only calls CustomerComparer.AreEqual
if (!dataBase.Contains(obj, equalityComparer))
//...
}
}
}
有没有人知道我该如何解决这个问题?那太棒了,我真的一直在努力解决这个巨大的性能问题。
编辑:
我在初始化哈希集时通过我的 EuqalityComparer 解决了这个问题!通过使用采用 IEqualityComparer 的构造函数重载,因此 var database = new HashSet(new CustomerComparer())
谢谢大家!
我在初始化哈希集时通过传递我的 EqualityComparer 解决了这个问题!使用了采用 IEqualityComparer 的构造函数重载,因此 var database = new HashSet(new CustomerComparer())
感谢Lee和NetMage在我的原创下发表评论post。