Почему бы вам не использовать long
вариант по умолчанию String.hashCode()
(где некоторые действительно умные ребята, безусловно, прилагают усилия для повышения его эффективности - не говоря уже о тысячах глаз разработчиков, которые уже смотрели на этот код)?
// adapted from String.hashCode()
public static long hash(String string) {
long h = 1125899906842597L; // prime
int len = string.length();
for (int i = 0; i < len; i++) {
h = 31*h + string.charAt(i);
}
return h;
}
Если вы ищете еще больше битов, вы можете использовать BigInteger
Редактировать:
Как я уже упоминал в комментарии к ответу @brianegge, вариантов использования хэшей с длиной более 32 бит не так много, и, скорее всего, нет ни одного случая использования хэшей с длиной более 64 битов:
Я мог бы представить огромную хеш-таблицу, распределенную по десяткам серверов, возможно, хранящую десятки миллиардов сопоставлений. Для такого сценария @brianegge по-прежнему имеет здесь правильную точку: 32-битное разрешение для 2 ^ 32 (около 4,3 миллиарда) различных хеш-ключей. Предполагая сильный алгоритм, вы все равно должны иметь довольно мало коллизий. С 64-битным (18,446,744,073 миллиарда различных ключей) вы, безусловно, сэкономите, независимо от того, какой сценарий вам нужен. Придумать варианты использования для 128-битных ключей (340 282 366 920 938 463 463 374 607 431 миллиарда возможных ключей) практически невозможно.
Чтобы объединить хэш для нескольких полей, просто сделайте XOR , умножьте единицу на простое и добавьте их:
long hash = MyHash.hash(string1) * 31 + MyHash.hash(string2);
Небольшое простое число присутствует там, чтобы избежать одинакового хеш-кода для переключаемых значений, то есть {'foo', 'bar'} и {'bar', 'foo'} не равны и должны иметь другой хеш-код. XOR плох, так как возвращает 0, если оба значения равны. Следовательно, {'foo', 'foo'} и {'bar', 'bar'} будут иметь одинаковый хэш-код.