Использование хэш-кода для уникального идентификатора
Я работаю в системе на основе 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