Согласованность хэш-кода() в строке Java
значение хэш-кода строки Java вычисляется как (строку.hashCode ()):
s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
есть ли какие-либо обстоятельства (скажем, версия JVM, поставщик и т. д.), при которых следующее выражение будет false?
boolean expression = "This is a Java string".hashCode() == 586653468
обновление #1: если вы утверждаете, что ответ "да, есть такие обстоятельства" - то, пожалуйста, приведите конкретный пример, когда "это строка Java".метод hashCode() != 586653468. Постарайтесь быть максимально конкретным / конкретным по возможности.
обновление #2: мы все знаем, что полагаться на детали реализации hashCode() плохо в целом. Однако я говорю конкретно о струне.hashCode () - поэтому, пожалуйста, держите ответ сосредоточенным на строке.hashCode (). Объект.hashCode () совершенно не имеет значения в контексте этого вопроса.
7 ответов:
Я могу видеть эту документацию еще в Java 1.2.
а это правда, что В общем вы не должны полагаться на реализацию хэш-кода, оставаясь прежним, теперь это документированное поведение для
java.lang.String, поэтому изменение его будет считаться нарушением существующих контрактов.везде, где это возможно, вы не должны полагаться на хэш-коды, остающиеся одинаковыми в разных версиях и т. д.-Но на мой взгляд
java.lang.Stringявляется частным случаем просто потому, что алгоритм и была определена... конечно, если вы готовы отказаться от совместимости с выпусками до того, как алгоритм был указан.
Я нашел что-то о JDK 1.0 и 1.1 и >= 1.2:
в JDK 1.0.x и 1.1.х хэш-код функция для длинных строк работает выборка каждого n-го символа. Этот довольно хорошо гарантировано, что у вас будет много строк хэширования к тому же значение, таким образом замедляя хэш-таблицу уважать. В JDK 1.2 функция был улучшен, чтобы умножить результат до сих пор 31 затем добавьте следующий характер в последовательности. Это немного медленнее, но намного лучше избегая столкновений. Источник: http://mindprod.com/jgloss/hashcode.html
Что - то другое, потому что вам, кажется, нужен номер: как насчет использования CRC32 или MD5 вместо хэш-кода, и вы хорошо идете-никаких обсуждений и никаких забот вообще...
вы не должны полагаться на хэш-код равен определенному значению. Только то, что он будет возвращать последовательные результаты в рамках одного и того же выполнения. В документах API говорится следующее:
общий контракт хэш-кода:
- всякий раз, когда он вызывается на один и тот же объект более одного раза во время выполнения приложения Java, метод hashCode должен последовательно возвращать одно и то же целое число, при условии отсутствия информации, используемой в равных сравнениях на объект модифицируется. Это целое число не должно оставаться последовательным от одного выполнения приложения к другому выполнению того же приложения.
EDIT Начиная с javadoc для строки.hashCode () указывает, как вычисляется хэш-код строки, любое нарушение этого будет нарушать публичную спецификацию API.
Как было сказано выше, в общем случае вы не должны полагаться на хэш-код класса, оставаясь тем же самым. Обратите внимание, что даже последующие запуски то же приложение на та же VM может создавать различные значения хэша. AFAIK хэш-функция Sun JVM вычисляет один и тот же хэш при каждом запуске, но это не гарантируется.
обратите внимание, что это не теоретически. Хэш-функция для java.ленг.Строка был изменен в JDK1. 2 (у старого хэша были проблемы с иерархическими строками, такими как URL-адреса или имена файлов, поскольку они, как правило, производят один и тот же хэш для строк, которые отличаются только в конце).
java.ленг.String-это особый случай, так как алгоритм его hashCode () (теперь) документирован, поэтому вы, вероятно, можете на это положиться. Я все равно считаю это плохой практикой. Если вам нужен хэш-алгоритм со специальными, документированными свойствами, просто напишите один : -).
другое (!) проблема, о которой нужно беспокоиться, - это возможное изменение реализации между ранними/поздними версиями Java. Я не верю, что детали реализации установлены в камне, и поэтому возможно обновление до будущее версия Java может вызвать проблемы.
суть в том, что я бы не полагался на реализацию
hashCode().возможно, вы можете выделить какую проблему вы на самом деле пытаетесь решить с помощью этого механизма, и которые будут освещены более подходящий подход.
просто ответить на ваш вопрос и не продолжать никаких дискуссий. Реализация Apache Harmony JDK, похоже, использует другой алгоритм, по крайней мере, он выглядит совершенно по-другому:
должен
public int hashCode() { int h = hash; if (h == 0) { int off = offset; char val[] = value; int len = count; for (int i = 0; i < len; i++) { h = 31*h + val[off++]; } hash = h; } return h; }Apache Harmony
public int hashCode() { if (hashCode == 0) { int hash = 0, multiplier = 1; for (int i = offset + count - 1; i >= offset; i--) { hash += value[i] * multiplier; int shifted = multiplier << 5; multiplier = shifted - multiplier; } hashCode = hash; } return hashCode; }Не стесняйтесь проверить это сами...
Если вас беспокоят изменения и, возможно, несовместимые виртуальные машины, просто скопируйте существующую реализацию хэш-кода в свой собственный класс утилиты и используйте ее для создания своих хэш-кодов .
Comments