У меня проблема с хеш-коллизиями с использованием коротких строк в .NET4.
РЕДАКТИРОВАТЬ: Я использую встроенную функцию хеширования строк в .NET.
Я реализую кеш, используя объекты, которые хранят направление конвертации, как это
public class MyClass
{
private string _from;
private string _to;
// More code here....
public MyClass(string from, string to)
{
this._from = from;
this._to = to;
}
public override int GetHashCode()
{
return string.Concat(this._from, this._to).GetHashCode();
}
public bool Equals(MyClass other)
{
return this.To == other.To && this.From == other.From;
}
public override bool Equals(object obj)
{
if (obj == null) return false;
if (this.GetType() != obj.GetType()) return false;
return Equals(obj as MyClass);
}
}
Это зависит от направления, и from
и to
представлены короткими строками, такими как «AAB» и «ABA».
Я получаю редкие коллизии хэшей с этими небольшими строками, я пробовал что-то простое, например, добавление соли (не сработало).
Проблема в том, что слишком много моих маленьких строк, таких как «AABABA», сталкивает свой хеш с обратным «ABAAAB» (обратите внимание, что это не реальные примеры, я понятия не имею, если AAB и ABA на самом деле вызывают столкновения!)
и я пошел на тяжелую работу, как реализация MD5 (которая работает, но НАМНОГО медленнее)
Я также реализовал предложение от Джона Скита здесь:
Должен ли я использовать конкатенацию моих строковых полей в качестве хеш-кода?
Это работает, но я не знаю, насколько надежно это с моими различными 3-символьными строками.
Как улучшить и стабилизировать хеширование небольших строк, не добавляя слишком много накладных расходов, как MD5?
РЕДАКТИРОВАТЬ: В ответ на несколько опубликованных ответов ... кэш реализован с использованием параллельных словарей с ключом из MyClass
, как указано выше. Если я заменим GetHashCode
в приведенном выше коде на что-то простое, например код @JonSkeet по ссылке, которую я разместил:
int hash = 17;
hash = hash * 23 + this._from.GetHashCode();
hash = hash * 23 + this._to.GetHashCode();
return hash;
Все работает как положено.
Стоит также отметить, что в этом конкретном случае использования кеш не используется в многопоточной среде, поэтому условия гонки отсутствуют.
РЕДАКТИРОВАТЬ: Я должен также отметить, что это неправильное поведение зависит от платформы. Он работает, как и предполагалось, на моем полностью обновленном компьютере с Win7x64, но не работает должным образом на компьютере без обновления Win7x64. Я не знаю, в каком объеме отсутствуют обновления, но я знаю, что в нем нет Win7 SP1 ... поэтому я могу предположить, что может быть также и фреймворк SP или обновление, в котором он также отсутствует.
РЕДАКТИРОВАТЬ: Как и предполагалось, моя проблема не была вызвана проблемой с функцией хеширования. У меня было неуловимое состояние гонки, поэтому оно работало на некоторых компьютерах, но не на других, а также почему «медленный» метод хеширования заставлял вещи работать правильно. Ответ, который я выбрал, был наиболее полезным для понимания, почему моя проблема не заключалась в коллизиях хеша в словаре.