Подтвердить что ты не робот

Реализация Java Array HashCode

Это нечетно. Сотрудник спросил о реализации myArray.hashCode() в java. Я думал, что знаю, но потом я провел несколько тестов. Проверьте код ниже. Странное мнение, что я заметил, это то, что когда я написал первый синус, результаты были разными. Обратите внимание, что почти так, как будто он сообщает адрес памяти и модифицирует класс, переместил адрес или что-то в этом роде. Просто подумал, что я поделюсь.

int[] foo = new int[100000];
java.util.Random rand = new java.util.Random();

for(int a = 0; a < foo.length; a++) foo[a] = rand.nextInt();

int[] bar = new int[100000];
int[] baz = new int[100000];
int[] bax = new int[100000];
for(int a = 0; a < foo.length; a++) bar[a] = baz[a] = bax[a] = foo[a];

System.out.println(foo.hashCode() + " ----- " + bar.hashCode() + " ----- " + baz.hashCode() +  " ----- " + bax.hashCode());

// returns 4097744 ----- 328041 ----- 2083945 ----- 2438296
// Consistently unless you modify the class.  Very weird
// Before adding the comments below it returned this:
// 4177328 ----- 4097744 ----- 328041 ----- 2083945


System.out.println("Equal ?? " +
  (java.util.Arrays.equals(foo, bar) && java.util.Arrays.equals(bar, baz) &&
  java.util.Arrays.equals(baz, bax) && java.util.Arrays.equals(foo, bax)));
4b9b3361

Ответ 1

Метод java.lang.Array hashCode наследуется от Object, что означает, что хэш-код зависит от ссылки. Чтобы получить хэш-код на основе содержимого массива, используйте Arrays.hashCode.

Остерегайтесь его мелкой реализации hashcode. Также присутствует глубокая реализация Arrays.deepHashCode.

Ответ 2

Массивы используют хэш-код по умолчанию, который основан на расположении памяти (но это не обязательно место памяти, так как это только int и все адреса памяти не подходят). Вы можете увидеть это, также распечатав результат System.identityHashCode(foo).

Массивы являются только equal, если они являются одинаковыми, идентичными массивами. Таким образом, хэш-коды массива будут только равными, как правило, если они являются одинаковыми, идентичный массив.

Ответ 3

Реализация по умолчанию для Object.hashCode() действительно возвращает значение указателя объекта, хотя это зависит от реализации. Например, 64-разрядная JVM может принимать указатель и XOR, а слова высокого и низкого порядка вместе. Подклассам рекомендуется переопределять это поведение, если это имеет смысл.

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

Обратите внимание, что java.util.Arrays предоставляет реализацию deepHashCode(), когда важно хеширование, основанное на содержимом массива, а не на личность самого массива.

Ответ 4

Я согласен с использованием java.util.Arrays.hashCode(или общей оболочки google guava Objects.hashcode), но имейте в виду, что это может вызвать проблемы, если вы используете Terracotta - см. эта ссылка