Использование хэш-кода для уникального идентификатора

Я работаю в системе на основе java, где мне нужно установить id для определенных элементов на визуальном дисплее. Одна категория элементов-строки, поэтому я решил использовать строку.метод hashCode () для получения уникального идентификатора для этих элементов.

проблема, с которой я столкнулся, заключается в том, что система, с которой я работаю в borks, если id отрицательный и String.hashCode часто возвращает отрицательные значения. Одно быстрое решение-просто использовать математику.abs () вокруг вызова хэш-кода, чтобы гарантировать положительный результат. Мне было интересно узнать об этом подходе, каковы шансы двух разных элементов иметь один и тот же хэш-код?

например, если одна строка возвращает хэш-код -10, а другая строка возвращает хэш-код 10, произойдет ошибка. В моей системе мы говорим о коллекциях объектов, которые обычно не больше 30 элементов, поэтому я не думаю, что это действительно будет проблемой, но мне любопытно, что говорит математика.

4 ответов


хэш-коды можно рассматривать как псевдослучайные числа. Статистически, с положительным int хэш-код вероятность столкновения между любыми двумя элементами достигает 50%, когда размер популяции составляет около 54K (и 77K для любой int). См.Таблица Вероятности Проблемы Дня Рождения для вероятности столкновения различных размеров хэш-код.

кроме того, ваша идея использовать Math.abs() один имеет недостатки: он не всегда возвращает положительное число! В 2-х комплимент арифметике, абсолютное значение Integer.MIN_VALUE - это само собой! Лихо, хэш-код "polygenelubricants" это значение.


хэши не уникальны, поэтому они не подходят для уникальный идентификатор.

что касается вероятности хэш-столкновения, вы можете прочитать о парадокс дней рождения. На самом деле(из того, что я помню) при рисовании из равномерного распределения N значений вы должны ожидать столкновения после рисования $\sqrt (N)$ (вы могли бы получить столкновение намного раньше). Проблема в том, что реализация Java hashCode (и особенно при хэшировании коротких строк) не обеспечивает равномерное распределение, так что столкновение произойдет гораздо раньше.


вы уже можете получить две строки с одним и тем же хэш-кодом. Это должно быть очевидно, если вы думаете, что у вас есть бесконечное количество строк и только 2^32 возможных хэш-кодов.

вы просто делаете это немного более вероятным при принятии абсолютного значения. Риск небольшой, но если вы нужно уникальный идентификатор, это не правильный подход.


что вы можете сделать, когда у вас есть только 30-50 значений, как вы сказали, это зарегистрировать каждую строку, которую вы получаете в HashMap вместе с запущенным счетчиком как значение:

HashMap StringMap = new HashMap<String,Integer>();

StringMap.add("Test",1);
StringMap.add("AnotherTest",2);

затем вы можете получить свой уникальный идентификатор, вызвав это:

StringMap.get("Test"); //returns 1