Я создал проект для сравнения таких вещей: http://code.google.com/p/hashingbench/ (Для хеш-таблиц с фильтрами цепочки, открытой адресации и Блума).
Помимо hashCode () ключа, вам нужно знать функцию «размазывания» (или «скремблирование», как я это называю в этом проекте) хеш-таблицы.Из этого списка функция размазывания HashMap является эквивалентом:
public int scramble(int h) {
h ^= (h >>> 20) ^ (h >>> 12);
return h ^ (h >>> 7) ^ (h >>> 4);
}
Таким образом, для столкновения в HashMap необходимо необходимых и достаточных условие следующее: scramble(k1.hashCode()) == scramble(k2.hashCode())
. Это всегда верно, если k1.hashCode() == k2.hashCode()
(в противном случае функция смазывания / скремблирования не будет быть функцией), поэтому достаточно , но не необходимое условие для возникновения столкновения.
Редактировать: На самом деле вышеуказанное необходимое и достаточное условие должно было быть compress(scramble(k1.hashCode())) == compress(scramble(k2.hashCode()))
- функция compress
принимает целое числои сопоставляет его с {0, ..., N-1}
, где N
- количество сегментов, поэтому он в основном выбирает сегмент.Обычно это просто реализуется как hash % N
, или когда размер хеш-таблицы равен степени двух (и это на самом деле побуждает иметь размер хеш-таблицы с степенью двойки), как hash & N
(быстрее).(«Сжатие» - это имя Гудрича и Тамассии, использованное для описания этого шага в Структуры данных и алгоритмы в Java ).Спасибо, что обратились к ILMTitan за обнаружением моей небрежности.
Другие реализации хеш-таблиц (ConcurrentHashMap, IdentityHashMap и т. Д.) Имеют другие потребности и используют другую функцию размазывания / скремблирования, поэтому вам нужно знать, о какой вы говорите.
(Например, функция размазывания HashMap была введена в действие, потому что люди использовали HashMap с объектами с наихудшим типом hashCode () для старой реализации HashMap со степенью двух таблиц без размазывания - объектыкоторые немного или совсем не различаются по своим младшим битам, которые использовались для выбора сегмента - например, new Integer(1 * 1024)
, new Integer(2 * 1024)
* и т. д. Как вы можете видеть, функция размазывания HashMap старается изо всех сил иметь все биты влияют на младшие биты).
Все они, тем не менее, должны хорошо работать в общих случаях - частный случай - это объекты, которые наследуют hashCode () системы.
PS: На самом деле, абсолютно безобразным случаем, побудившим разработчиков добавить функцию размазывания, является hashCode () типа Floats / Doubles и использование в качестве ключей значений: 1.0, 2.0, 3.0, 4.0 ..., все они имеют одинаковые (нулевые) младшие биты.Это старый отчет об ошибке: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4669519