Значение hashCode Java String вычисляется как ( String.hashCode () ):
s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
Существуют ли какие-либо обстоятельства (например, версия JVM, поставщик и т. Д.), При которых следующее выражение будет оцениваться как ложное?
boolean expression = "This is a Java string".hashCode() == 586653468
Обновление №1: если вы утверждаете, что ответ - «да, бывают такие обстоятельства», то приведите конкретный пример того, когда «Это строка Java» .hashCode ()! = 586653468. Постарайтесь быть максимально конкретным / конкретным насколько возможно.
Обновление №2: все мы знаем, что полагаться на детали реализации hashCode () в целом плохо. Однако я говорю конкретно о String.hashCode (), поэтому, пожалуйста, сосредоточьтесь на String.hashCode (). Object.hashCode () совершенно не имеет значения в контексте этого вопроса.
Ответы:
Я могу видеть эту документацию еще в Java 1.2.
Хотя в целом вы не должны полагаться на то, что реализация хэш-кода останется прежней, теперь это задокументированное поведение для
java.lang.String
, поэтому его изменение будет считаться нарушением существующих контрактов.Везде , где это возможно, вы не должны полагаться на хэш - кодов остаются теми же в разных версиях и т.д. - но в моем сознании
java.lang.String
это особый случай , просто потому , что алгоритм был задан ... до тех пор , пока вы готовы отказаться от совместимости с выпусками до Алгоритм, конечно, уточнялся.источник
Я нашел кое-что о JDK 1.0 и 1.1 и> = 1.2:
Что-то другое, потому что вам, кажется, нужен номер: как насчет использования CRC32 или MD5 вместо хэш-кода, и все готово - никаких дискуссий и никаких забот ...
источник
Вы не должны полагаться на то, что хэш-код равен определенному значению. Просто он вернет согласованные результаты в одном и том же выполнении. В документации по API говорится следующее:
EDIT Поскольку Javadoc для String.hashCode () определяет , как вычисляется хэш - код в строку, любое нарушение этого нарушило бы спецификацию общественного API.
источник
Как было сказано выше, в целом не следует полагаться на то, что хеш-код класса остается неизменным. Обратите внимание, что даже последующие запуски одного и того же приложения на одной виртуальной машине могут давать разные хеш-значения. AFAIK хеш-функция Sun JVM вычисляет один и тот же хеш при каждом запуске, но это не гарантируется.
Обратите внимание, что это не теоретически. Хеш-функция для java.lang.String была изменена в JDK1.2 (у старого хеша были проблемы с иерархическими строками, такими как URL-адреса или имена файлов, поскольку он, как правило, давал один и тот же хеш для строк, которые различались только в конце).
java.lang.String - это особый случай, поскольку алгоритм его hashCode () (сейчас) задокументирован, так что вы, вероятно, можете положиться на это. Я все равно считаю это плохой практикой. Если вам нужен алгоритм хеширования со специальными задокументированными свойствами, просто напишите его :-).
источник
Еще одна (!) Проблема, о которой нужно беспокоиться, - это возможное изменение реализации между ранними и поздними версиями Java. Я не верю, что детали реализации высечены на камне, и поэтому потенциально обновление до будущей версии Java может вызвать проблемы.
Суть в том, что я бы не стал полагаться на реализацию
hashCode()
.Возможно, вы сможете выделить, какую проблему на самом деле пытаетесь решить с помощью этого механизма, и это выделит более подходящий подход.
источник
switch
операторы над строками компилируются в код, основанный на конкретном фиксированном хеш-коде, изменения вString
алгоритме хеш-кода определенно нарушат существующий код…Просто чтобы ответить на ваш вопрос и не продолжать никаких дискуссий. Реализация Apache Harmony JDK, похоже, использует другой алгоритм, по крайней мере, он выглядит совершенно иначе:
Sun JDK
Апач Гармония
Не стесняйтесь проверить это сами ...
источник
s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
если я не ошибаюсь, это потому, что Android использует реализацию объекта String от Sun без изменений.Если вас беспокоят изменения и, возможно, несовместимые виртуальные машины, просто скопируйте существующую реализацию хэш-кода в свой собственный служебный класс и используйте его для генерации хэш-кодов.
источник
Хэш-код будет рассчитан на основе значений ASCII символов в строке.
Это реализация в классе String выглядит следующим образом
Коллизии в хэш-коде неизбежны. Например, строки «Ea» и «FB» дают тот же хэш-код, что и 2236.
источник