HashCode дает отрицательные значения

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

int combine = (srcadd + dstadd + sourceport + destinationport + protocol).hashCode();
System.out.println(combine);

person Xara    schedule 12.02.2012    source источник
comment
Почему хеш-коды не могут быть отрицательными? AFAIK, единственное требование к ним - быть равными для одинаковых объектов ..   -  person user1096188    schedule 12.02.2012


Ответы (3)


Я не думаю, что хеш-значения должны быть отрицательными.

Почему нет? Иметь отрицательные хэш-коды вполне допустимо. Большинство способов создания хэш-кода естественным образом заканчиваются отрицательными значениями, и все, что с ними связано, должно это учитывать. Однако я бы рассмотрел другой подход к созданию ваших хэш-кодов, например

int hash = 17;
hash = hash * 31 + srcadd.hashCode();
hash = hash * 31 + dstadd.hashCode();
hash = hash * 31 + sourceport; // I'm assuming this is an int...
hash = hash * 31 + destinationport; // ditto
hash = hash * 31 + protocol.hashCode();
return hash;

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

Обратите внимание, что это также улучшило бы читаемость вашего кода, если бы вы избегали сокращений и использовали верблюжий корпус, например sourceAddress вместо srcadd.

person Jon Skeet    schedule 12.02.2012
comment
На самом деле на каком-то форуме было написано, что hashCode - это способ вычисления небольшого (32-битного) цифрового ключа дайджеста из длинной строки. Итак, я, хотя его диапазон составляет 2 ^ 32, а это от 0 до 2 ^ 32 - person Xara; 12.02.2012
comment
@Zara: Но int не поддерживает числа больше 2 ^ 31-1 ... это 32-битное значение, но в диапазоне со знаком. - person Jon Skeet; 12.02.2012
comment
@JonSkeet Не могли бы вы объяснить, почему вы устанавливаете hash = 17 и умножаете на 31? Я немного запутался в этой детали. - person bsheps; 10.03.2019
comment
@bsheps: Если честно, это числа, скопированные с Джоша Блоха. В другом месте есть целые темы о выборе чисел для этого подхода. - person Jon Skeet; 10.03.2019

иногда сам расчет hashcode выходит за рамки Integer.MAX_VALUE, то есть 2147483647. тогда получается отрицательное целое число после overflow. Отрицательный хэш-код абсолютно допустим!

person Pravat Panda    schedule 30.07.2013

Совершенно законно иметь отрицательные хеш-коды, и если вы ищете хеш-значения, которые используются в коллекциях на основе хешей, вы можете использовать Math.abs(hash) . Это также может дать вам отрицательные числа, когда хэш больше 2 ^ 31, и лучший способ - использовать маску сдвига (key.hashCode() & 0x7fffffff) % M, где M - размер таблицы.

person Milky    schedule 29.11.2013
comment
Я не понимаю, почему бы вам просто не использовать Math.abs (hash). Насколько я понимаю, Math.abs () вернет отрицательное значение только для int.MIN_VALUE. Если hash = key.hashCode ()% M, тогда единственный способ получить hash == int.MIN_VALUE - это M ›int.MAX_VALUE, и в этом случае вам все равно придется использовать longs для индексации таблицы. - person jkindwall; 21.11.2015
comment
Чем больше 2 ^ 31, этот ответ на самом деле означает более 31 двоичных цифр, а не больше целого числа, чем 2 ^ 31. Почему (key.hashCode() & 0x7fffffff)? Потому что это простая одноступенчатая двоичная операция над результатом hashCode(), которая должна (или могла) выполняться быстрее, чем Math.abs(). - person Ogre Psalm33; 20.07.2017