Является ли Java HashMap.clear() и remove() эффективной?
Рассмотрим следующий код HashMap.clear()
:
/**
* Removes all of the mappings from this map.
* The map will be empty after this call returns.
*/
public void clear() {
modCount++;
Entry[] tab = table;
for (int i = 0; i < tab.length; i++)
tab[i] = null;
size = 0;
}
Кажется, что внутренний массив (table
) объектов Entry
никогда не сжимается. Поэтому, когда я добавляю к карте 10000 элементов, и после этого вызова map.clear()
, он будет содержать 10000 нулей в нем внутреннего массива. Итак, мой вопрос: как JVM обрабатывает этот массив ничего, и, следовательно, эффективна HashMap
?
Ответы
Ответ 1
Идея состоит в том, что clear()
вызывается только тогда, когда вы хотите повторно использовать HashMap
. Повторное использование объекта должно выполняться только по той же причине, что и раньше, поэтому есть вероятность, что у вас будет примерно одинаковое количество записей. Чтобы избежать ненужного сокращения и изменения размера Map
, емкость сохраняется одинаковой при вызове clear()
.
Если все, что вы хотите сделать, это сбросить данные в Map
, тогда вам не нужно (и на самом деле не следует) называть clear()
на нем, но просто очистить все ссылки на Map
себя, в в этом случае в конечном итоге будет собран мусор.
Ответ 2
Посмотрев на исходный код, он выглядит как HashMap
никогда не сжимается. Метод resize
вызывается для удвоения размера, когда это требуется, но не имеет ничего ala ArrayList.trimToSize()
.
Если вы используете HashMap
таким образом, что он растет и сильно сокращается, вы можете просто создать новый HashMap
вместо вызова clear()
.
Ответ 3
Вы правы, но учитывая, что увеличение массива является гораздо более дорогостоящей операцией, для HashMap неразумно думать "когда пользователь увеличил массив, скорее всего, ему понадобится массив такого размера позже", и просто оставьте массив, а не уменьшайте его и рискуете, чтобы потом дорого его расширять позже. Полагаю, это эвристический подход - вы тоже можете защищать и наоборот.
Ответ 4
Еще одна вещь, которую следует учитывать, состоит в том, что каждый элемент в table
является просто ссылкой. Установка этих записей в значение null приведет к удалению ссылок из элементов вашего Map
, которые затем будут бесплатными для сбора мусора. Так что это не так, как будто вы вообще не освобождаете память.
Однако, если вам нужно освободить даже память, используемую самим Map
, тогда вы должны отпустить ее в соответствии с предложением Йоахима Зауэра.