Реализация Java Array HashCode - PullRequest
       24

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

47 голосов
/ 13 апреля 2009

Это странно. Сотрудник спросил о реализации 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)));

Ответы [ 4 ]

88 голосов
/ 13 апреля 2009

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

Остерегайтесь, хотя это мелкая реализация хэш-кода. Глубокая реализация также присутствует Arrays.deepHashCode.

4 голосов
/ 13 апреля 2009

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

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

2 голосов
/ 27 октября 2010

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

2 голосов
/ 13 апреля 2009

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

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

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

...