Согласованность хэш-кода() в строке 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 () совершенно не имеет значения в контексте этого вопроса.

227   7  

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;
}

Не стесняйтесь проверить это сами...

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

    Ничего не найдено.

Добавить ответ:
Отменить.