Карта представляет собой «расширяемую» структуру: когда она достигает своего предела, ее размер изменяется. Так что вполне возможно, что, скажем, 40% пространства, используемого вашей картой, на самом деле пусты. Если вы знаете, сколько записей будет на вашей карте, вы можете использовать специальные конструкторы для оптимального размера вашей карты:
Map<xx,yy> map = new HashMap<> (length, 1);
Даже если вы это сделаете, карта все равно будет занимать больше места, чем фактический размер содержащихся в ней элементов.
Более подробно: размер HashMap удваивается, когда он достигает (capacity * loadFactor). Коэффициент загрузки по умолчанию для HashMap равен 0,75.
Пример:
- Представьте, что ваша карта имеет емкость (размер) 10 000 записей.
- Затем вы помещаете на карту 7501 запись. Вместимость * коэффициент нагрузки = 10 000 * 0,75 = 7 500
- Таким образом, ваша хэш-карта достигла порога изменения размера и изменяется до (емкость * 2) = 20 000, хотя у вас всего 7 501 запись. Это тратит много места.
ИЗМЕНИТЬ
Этот простой код дает вам представление о том, что происходит на практике — вывод:
threshold of empty map = 8192
size of empty map = 35792
threshold of filled map = 8192
size of filled map = 1181712
threshold with one more entry = 16384
size with one more entry = 66640
который показывает, что если последний элемент, который вы добавляете, вызывает изменение размера карты, он может искусственно увеличить размер вашей карты. Правда, это не объясняет всего эффекта, который вы наблюдаете.
public static void main(String[] args) throws java.lang.Exception {
Field f = HashMap.class.getDeclaredField("threshold");
f.setAccessible(true);
long mem = Runtime.getRuntime().freeMemory();
Map<String, String> map = new HashMap<>(2 << 12, 1); // 8,192
System.out.println("threshold of empty map = " + f.get(map));
System.out.println("size of empty map = " + (mem - Runtime.getRuntime().freeMemory()));
mem = Runtime.getRuntime().freeMemory();
for (int i = 0; i < 8192; i++) {
map.put(String.valueOf(i), String.valueOf(i));
}
System.out.println("threshold of filled map = " + f.get(map));
System.out.println("size of filled map = " + (mem - Runtime.getRuntime().freeMemory()));
mem = Runtime.getRuntime().freeMemory();
map.put("a", "a");
System.out.println("threshold with one more entry = " + f.get(map));
System.out.println("size with one more entry = " + (mem - Runtime.getRuntime().freeMemory()));
}
person
assylias
schedule
01.11.2012