Java - Как функция hashCode () может выводить небольшое (или отрицательное) число, когда строка большая

1

Я сделал эту функцию, и она работает так же, как и оригинальная функция Java, когда вы вводите что-то короткое, но если я ввожу что-то большее, чем 5-7 символов, то я получаю очень большое количество. (И не правильный хэш-код)

Вот формула хэш-функции Java:

s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]

Упрощенный (работает только для коротких строк):

s = "abc" //String
n = 3 //Lenght of the String
s[0] = 'a'. ASCII code of 'a' = 97.
97 * (31 ^ (n - 1))
97 * (31 ^ (2))
97 * 961 = 93217

s[1] = 'b'. ASCII code of 'b' = 98.
98 * (31 ^ (n - 2))
98 * (31 ^ 1)
98 * 31 = 3038

s[2] = 'c'. ASCII code of 'c' = 99.
99 * (31 ^ (n - 3))
99 * (31 ^ 0)
99 * 1 = 99

93217 + 3038 + 99 = 96354 //

Я хочу знать, как Java делает хэш небольшим, даже когда я вхожу в огромную строку.

Java hashcode of "Hello" - 69609650
My hashcode of "Hello" - 69609650


Java hashcode of "Welcome to Tutorialspoint.com" - 1186874997
My hashcode of "Welcome to Tutorialspoint.com" - 5.17809991536626e+43

Также, как хэш может быть отрицательным, если мы складываем числа?

Теги:
string
hash

3 ответа

2
Лучший ответ

String hashCode включает только добавление и умножение int, поэтому он приводит к int, который может переполняться (следовательно, отрицательные значения).

public int hashCode() {
    int h = hash;
    int len = count;
    if (h == 0 && len > 0) {
        int off = offset;
        char val[] = value;
        for (int i = 0; i < len; i++) {
            h = 31*h + val[off++];
        }
        hash = h;
    }
    return h;
}

Исходя из вашего значения 5.17809991536626e+43, похоже, что вы выполняете вычисления с плавающей запятой (возможно, вы используете Math.pow() который возвращает double), которые дают разные результаты для больших чисел.

3

Я подозреваю, что ваша реализация (которую вы не показали) использует BigInteger или что-то подобное. Java просто использует int - поэтому, когда он переполняет диапазон положительных 31-битных целых чисел, он переходит в большие отрицательные целые числа, а затем, когда вы добавляете больше (положительных) значений, вы получите небольшие отрицательные целые числа, а затем небольшие положительные целые числа, затем большие положительные целые числа и обратно к большим отрицательным целым числам.

1

Исходный код для String$hashCode():

 1494       public int hashCode() {
 1495           int h = hash;
 1496           if (h == 0 && count > 0) {
 1497               int off = offset;
 1498               char val[] = value;
 1499               int len = count;
 1500   
 1501               for (int i = 0; i < len; i++) {
 1502                   h = 31*h + val[off++];
 1503               }
 1504               hash = h;
 1505           }
 1506           return h;
 1507       }

int представляет собой целое число со знаком на 4 байта, и оно будет просто переполняться во время вычисления хеша, давая значение, которое может быть отрицательным, но всегда связано с int.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню