GroupBy on strings(hashcode collision)

时间:2013-07-26 01:08:13

标签: c# linq

我有一个字符串数组(约2000),我想使用 IEnumerable.GroupBy 对相等的字符串进行分组。

问题是虽然存在许多哈希冲突,例如“神秘”“井”。这可能是因为GroupBy使用了 GetHashCode(),它返回的int太小了(或者String类的GetHashCode函数没有很好地实现)。

我想您可以尝试实现重写的 GetHashCode 函数或定义自定义 IEqualityComparer 并使用不同的哈希码,但是没有任何方法可以直接比较它们或不同?我知道这需要更长的时间,但只需少量就可以接受。我怎么能解决这个问题?

1 个答案:

答案 0 :(得分:2)

GroupBy on strings只会将相同的字符串组合在一起,无论它们是否具有相同的哈希码。由于GroupBy在底层使用哈希表,因此许多具有相同哈希码的不同字符串可能会略微降低性能,但仍会给出正确的答案。

为了证明这一点,请注意GroupBy即使使用具有可怕散列函数的自定义IEqualityComparer也能正常工作:

void Main()
{
    var groups = new[] { "a", "a", "b", "b", "c", "c" }.GroupBy(s => s, new BadComparer())
        .Select(g => string.Join(",", g))
        .ToArray();
    Console.WriteLine(string.Join(Environment.NewLine, groups));
    // this prints:
    // a,a
    // b,b
    // c,c      
}

public class BadComparer : IEqualityComparer<string> {
    public bool Equals(string a, string b) { return a == b; }
    public int GetHashCode(string s) { return 0; }
}

另请注意,按字符串本身而不是哈希代码进行分组非常重要:

myStrings.GroupBy(s => s) // works

myStrings.GroupBy(s => s.GetHashCode()) // doesn't work