два неравных объекта с одинаковым хэш-кодом
hashCode() и equals () концепция
1) Если два объекта равны в соответствии с equal (), то вызов метода hashcode для каждого из этих двух объектов должен производить один и тот же хэш-код.
и
2) не требуется, чтобы если два объекта не равны в соответствии с equal (), то вызов метода hashcode для каждого из двух объектов должен давать разные значения.
Я пробовал и понял первый и это код для первого пункта.
public class Test {
public static void main(String[] args) {
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
map.put(1, 11);
map.put(4, 11);
System.out.println(map.hashCode());
Map<Integer, Integer> map1 = new HashMap<Integer, Integer>();
map1.put(1, 11);
map1.put(4, 11);
System.out.println(map1.hashCode());
if (map.equals(map1)) {
System.out.println("equal ");
}
}
}
вышеуказанная программа дает один и тот же хэш-код для двух разных объектов.
может кто-нибудь объяснить мне на примере,как два разных объекта, неравные в соответствии с equals (), имеют один и тот же хэш-код.
8 ответов
2) это не требуется что если два объекта неравный согласно equal (), затем вызов метода hashcode для каждого из двух объектов должен создавать различные значения.
в зависимости от функции хэширования 2 разных объекта могут иметь один и тот же хэш-код. Однако 2 объекта, которые одинаковы, должны давать тот же результат при хэшировании (если кто-то не реализовал функцию хэширования со случайными числами, в этом случае это бесполезно)
например, если я хеширую целые числа, а моя функция хеширования просто (n % 10)
тут и даст тот же результат. Это не означает, что эти числа одинаковы.
пример со строками (все строки ниже имеют хэш-код 0):
public static void main(String[] args) {
List<String> list = Arrays.asList("pollinating sandboxes",
"amusement & hemophilias",
"schoolworks = perversive",
"electrolysissweeteners.net",
"constitutionalunstableness.net",
"grinnerslaphappier.org",
"BLEACHINGFEMININELY.NET",
"WWW.BUMRACEGOERS.ORG",
"WWW.RACCOONPRUDENTIALS.NET",
"Microcomputers: the unredeemed lollipop...",
"Incentively, my dear, I don't tessellate a derangement.",
"A person who never yodelled an apology, never preened vocalizing transsexuals.");
for (String s : list) {
System.out.println(s.hashCode());
}
}
(похищенных из этот пост).
hashCode () имеет 32-разрядные возможные значения. Ваши объекты могут иметь гораздо больше, чем это, поэтому у вас будут некоторые объекты с тем же хэш-кодом, т. е. вы не можете гарантировать, что они будут уникальными.
Это ухудшается в хэш-коллекции ограниченного размера. Максимальная емкость HashMap составляет 1
Примечание: На HotSpot JVM, объект по умолчанию.hashCode () никогда не отрицателен, т. е. только 31-бит, хотя я не уверен, почему.
Если вы хотите создать много объектов с тем же хэш-кодом, посмотрите долго.
// from Long
public int hashCode() {
return (int)(value ^ (value >>> 32));
}
for(long i = Integer.MIN_VALUE; i < Integer.MAX_VALUE;i++) {
Long l = (i << 32) + i;
System.out.print(l.hashCode()+" ");
if (i % 100 == 0)
System.out.println();
}
это будет генерировать 4 миллиарда длиной все с хэш-кодом 0.
цель hashCode
включить следующую аксиому и следствие:
Если кто-то знает хэш-коды двух объектов, и эти хэш-коды не совпадают, не нужно беспокоиться о том, чтобы исследовать объекты дальше, чтобы знать, что объекты не будут совпадать. Даже если два произвольно выбранных несопоставимых объекта будут иметь 10%-ную вероятность совпадения хэш-кодов, тестирование хэш-кодов позволит исключить 90% сравнений, которые в противном случае понадобились бы. Не такая большая победа, как устранение 99,99%, но тем не менее определенно стоит.
знание того, что ни один из объектов в группе не имеет определенного хэш-кода, означает, что ни один из объектов в этой группе не будет соответствовать объекту с этим хэш-кодом. Если бы кто-то разделил коллекцию объектов на те, чей хэш-код был четным числом, и те, чей хэш был нечетным, и хотел бы найти, есть ли у него данный элемент, чей хэш-код оказался четным, было бы нет необходимости изучать что-либо в коллекции нечетных хэш-элементов. Аналогично, не было бы необходимости искать элемент нечетного хэша в коллекции четного хэша. Таким образом, даже двухзначный хэш может ускорить поиск почти наполовину. Если разделить коллекцию на более мелкие разделы, можно ускорить процесс еще больше.
отметим, что hashCode()
предложит наибольшее преимущество, если каждый другой элемент возвращает другой хэш, но он может предложить существенную выгоду, даже если многие элементы имеют одинаковое значение хэша. Разница между 90% сбережений и 99,99% сбережений часто намного больше, чем цифры могли бы предложить, и, таким образом, если можно разумно легко улучшить вещи до 99%, 99,9% или лучше, нужно сделать это, но разница между нулевыми ложными совпадениями и несколькими ложными совпадениями в коллекции довольно мала.
Я не очень просто понять, если вы знаете, как реализуется HashMap, и это цель. Hashmap принимает большой набор значений и разбивает их на гораздо меньшие наборы(ведра) для гораздо более быстрого извлечения элементов. В основном вам нужно искать только одно ведро вместо полного списка для вашего элемента. Ведра находятся в массиве, где индекс является хэш-кодом. Каждое ведро содержит связанный список элементов с одинаковым хэш-кодом, но не равно(). Я думаю, что в Java 8 они переключается на использование treemap, когда размеры ковша становятся большими.
Это довольно просто на самом деле,
Сначала мы должны знать, что хэш-код.
в java хэш-код-это простое 32-битное целое число со знаком, которое каким-то образом получено из данных, о которых идет речь. Целочисленные типы обычно просто (Int Data) Mod (некоторое разумное Большое Простое Число).
давайте сделаем простой хэш на целых числах.
Определить:
public int hash(int num){ return num % 19 ; }
в этом случае как 19, так и 38 вернут хэш-значение 0.
строка типы, хэш получается из отдельных символов и каждой позиции в строке, разделенной на достаточно большое число. (Или, в случае Java, игнорируя переполнение в 32-битной сумме).
учитывая, что существует произвольно много строк, и существует ограниченное количество хэш-кодов (2^32) для строки, принцип голубиной дыры утверждает, что есть по крайней мере две разные строки, которые приводят к одному и тому же хэш-коду.
Actullay, эта ссылка объясняет, что происходит, если хэш-код равен более четко.
http://www.javamadesoeasy.com/2015/02/hashmap-custom-implementation.html
Я понимаю, что хэш-код является числовым представлением адреса памяти, но не является фактическим адресом. Его можно изменить, не влияя на фактический адрес. Таким образом, должно быть возможно установить все объекты на один и тот же хэш-код, даже если они все совершенно разные. Подумайте, что все в одном квартале внезапно имеют один и тот же адрес. Они действительно разные люди, но теперь у всех один и тот же адрес. Их дом не сдвинулся с места. подросток просто обозначил всех как "100 N. Main".
Я довольно новичок в Java, поэтому примите мой ответ с некоторой осторожностью.