如何针对这种情况实现GetHashCode
本文关键字:情况 实现 GetHashCode 何针 | 更新日期: 2023-09-27 18:19:30
我正在尝试实现一个IEqualityComparer<string>
,它基本上比较两个字符串,(假设我们有两个字符串x
和y
)如果x
以y
开头,或者y
以x
开头,它们应该被视为相等。
public bool Equals(string x, string y)
{
return x.StartsWith(y) || y.StartsWith(x);
}
public int GetHashCode(string obj)
{
return obj.GetHashCode();
}
当然,实现Equals
方法很容易。但GetHashCode
不是,我想不出任何方法来正确实现它。我写了一个这样的测试程序:
string[] values = {"hell", "hello", "foo", "fooooo"};
var result = values.Distinct(new StringComparer());
foreach(var x in result)
Console.WriteLine(x);
由于GetHashCode
:,我得到了错误的结果
hell
hello
foo
fooooo
显然,我可以通过从GetHashCode
为所有值返回相同的值来强制调用Equals
方法,但我想知道是否有其他方法可以实现它,因为性能至关重要。有没有一种方法可以针对我的情况正确地实现GetHashCode
方法?
注意:我知道它很模糊,但我找不到更好的标题,如果你有更好的想法,你可以自由编辑。
编辑:我将在web URL中使用此逻辑。在我的情况下,前20个字符是相等的。例如:
http://www.foo.com/bar?id=3
http://www.foo.com/bar?id=3&fooId=23
问题在于平等的定义:平等必须是可传递的。但你的情况并非如此。取以下三个值:
* f
* freeze
* foo
然后是f == freeze
和foo == f
,而不是freeze != foo
。
另请参阅MSDN关于实现Equals方法的内容,其中写道:
当且仅当
x.Equals(z)
返回真时,(x.Equals(y) && y.Equals(z))
返回真。
平等的正确定义产生了被认为是平等的不同的价值观。如果你有这些,你可以为每个集合定义一个"规范"表示,并计算规范值的哈希,这样每个集合都有自己的哈希代码。但这只适用于传递性的运算(以及交换性和自反性,这两个性质都在你的定义中)。
由于你对等式的定义是不可传递的,你不能定义这样的集合,所以你也找不到合适的哈希码。
但这也引发了其他问题。举个例子:
string[] values = { "hell", "hello", "foo", "fooooo" };
var result = values.Distinct(new StringComparer());
您希望result
中包含哪些值?你总是想要最短的版本吗?您的代码不会保证这一点,结果将取决于Distinct
的内部实现。
实现EqualityComparer
可能是解决实际问题的次优方法。你想达到什么目的?
由于字符串彼此相等,这取决于您将它们与哪个字符串进行比较,因此任何字符串都可以与另一个字符串相等。因此,只有一种方法可以实现CCD_ 22方法;为所有字符串返回相同的值:
public int GetHashCode(string obj) {
return 0;
}
这自然会造成可怕的分配。字典的查找时间是O(n),而不是O(1),但它是有效的,而且这是使它适用于这种相等比较的唯一方法。