Ответ
Теоретически количество объектов в одном бакете HashMap ограничено только доступной памятью, но структура хранения меняется для сохранения производительности.
Эволюция структуры бакета:
- До Java 8: Коллизии разрешались через связный список. В худшем случае (все ключи попали в один бакет) производительность деградировала до O(n).
- Java 8 и выше: При достижении порога
TREEIFY_THRESHOLD = 8элементов в одном бакете связный список преобразуется в сбалансированное красно-черное дерево. Это ограничивает время поиска в худшем случае до O(log n).
Практический пример коллизии:
// Ключ с постоянным хэш-кодом
class BadHashKey {
int id;
BadHashKey(int id) { this.id = id; }
@Override
public int hashCode() { return 1; } // Все объекты попадут в один бакет
@Override
public boolean equals(Object o) { /* реализация */ }
}
HashMap<BadHashKey, String> map = new HashMap<>();
for (int i = 0; i < 20; i++) {
map.put(new BadHashKey(i), "Value" + i);
}
// После 8-го элемента список в бакете станет деревом.
Важные константы:
TREEIFY_THRESHOLD = 8– порог преобразования списка в дерево.UNTREEIFY_THRESHOLD = 6– порог обратного преобразования дерева в список (при удалении элементов).MIN_TREEIFY_CAPACITY = 64– минимальная общая емкостьHashMapдля активации преобразования.
Вывод: Жесткого лимита нет, но HashMap автоматически оптимизирует хранение при большом числе коллизий, чтобы избежать катастрофического падения производительности.