Разница между новыми HashMap (int) и guava Maps.newHashMapWithExpectedSize(int)

В Java вы можете создать новый HashMap для хранения определенного количества элементов, например:

Map m = new HashMap(100);

Guava предоставляет метод Maps.newHashMapWithExpectedSize(int), который я ожидаю просто вызвать HashMap(int). Но он этого не делает, вместо этого он вычисляет свою собственную емкость и использует это.

Почему newHashMapWithExpectedSize делает свою собственную вещь и почему я хочу использовать ее непосредственно при вызове new HashMap(int)?

Ответ 1

Вы прочитали метод Javadoc?

Создает экземпляр HashMap с достаточно высокой "начальной емкостью", в которой он должен содержать элементы expectedSize без роста.

Обратите внимание, что параметр "начальный размер" конструктора new HashMap(int) указывает исходный размер хэш-таблицы, в которой хранятся записи, что в основном представляет собой деталь реализации, которую вам не нужно заботиться. Хэш-таблица будет изменять размер, если она превышает коэффициент загрузки карты (который по умолчанию равен 0,75), а это означает, что если вы укажете начальную емкость 16 и затем добавите 16 записей на карту, хэш-таблица почти наверняка будет изменена.

С помощью метода Guava, если вы укажете ожидаемый размер 16 и затем добавьте 16 записей, хэш-таблица не должна изменяться.

Ответ 2

Аргумент конструктора HashMap - это емкость карты, т.е. количество ведер.

Итак, если вы передадите 10 в качестве аргумента и сохраните 8 ключей на карте, будет достигнут порог переименования (75% по умолчанию), и карта будет переименована.

С другой стороны, аргумент, переданный newHashMapWithExpectedSize(), является ожидаемым размером карты. Итак, если вы пройдете 10, Guava создаст карту с достаточным количеством ведер, чтобы убедиться, что карта не перефразирует при вставке 10 элементов: по крайней мере 14 ведер.

Ответ 3

Гуава просто умножает размер, переданный 2 (безопасным способом), и вызывает обычный конструктор hashmap. Это делает его более разреженным, так что при хэшировании происходит меньше конфликтов.

В javadoc для расчета пропускной способности упоминается, что он вычисляет значение емкости, так что хэш-карта заполняется от 25% до 50%, что находится далеко от порога, который вызывает изменение размера.

Стандартная библиотека округляет ожидаемый размер до ближайшей мощности 2 и выделяет это как размер, а затем устанавливает порог для изменения размера до 75%. Если бы мы случайно запросили размеры, стандартная библиотека изменила бы размер в 50% случаев.

Если избежать порога, это будет единственным соображением, и умножить его на 1.34 будет достаточно, чтобы иметь достаточно места, чтобы избежать изменения размера при заполнении его ожидаемым размером элементов.

Похоже, типичная скорость и космос, а инженеры Google - более быстрые уроды, а инженеры Sun/Oracle - больше космических гаек.