Изменение размера поведения Карт в Java - PullRequest
1 голос
/ 21 мая 2019

Мне нужно знать, когда карта в Java увеличивается. Для этого мне нужна формула для расчета хорошей начальной емкости.

В моем проекте мне нужна большая карта, которая содержит большие объекты. Поэтому я хотел бы предотвратить изменение размера карты, указав подходящую начальную емкость. С помощью отражения я посмотрел на поведение карт.

package com.company;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;

public class Main {

    public static void main(String[] args) {

        Map m  = new HashMap();
        int lastCapacity = 0, currentCapacity = 0;
        for (int i = 1; i <= 100_000; i++) {
            m.put(i,i);
            currentCapacity = getHashMapCapacity(m);
            if (currentCapacity>lastCapacity){
                System.out.println(lastCapacity+" --> "+currentCapacity+" at "+i+" entries.");
                lastCapacity=currentCapacity;
            }
        }
    }

    public static int getHashMapCapacity(Map m){
        int size=0;
        Field tableField = null;
        try {
            tableField = HashMap.class.getDeclaredField("table");
            tableField.setAccessible(true);
            Object[] table = (Object[]) tableField.get(m);
            size = table == null ? 0 : table.length;
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return size;
    }
}

Вывод был:

0 -> 16 при 1 записи.

16 -> 32 при 13 записях.

32 -> 64 при 25 записях.

64 -> 128 при 49 записях.

128 -> 256 при 97 записях.

256 -> 512 при 193 записях.

512 -> 1024 при 385 записях.

1024 -> 2048 при 769 записях.

2048 -> 4096 при 1537 записях.

4096 -> 8192 при 3073 записях.

8192 -> 16384 при 6145 записях.

16384 -> 32768 при 12289 записях.

32768 -> 65536 при 24577 записях.

65536 -> 131072 при 49153 записях.

131072 -> 262144 на 98305 записей.

Можно ли предположить, что карта всегда ведет себя таким образом? Есть ли различия между Java 7 и Java 8?

Ответы [ 2 ]

0 голосов
/ 21 мая 2019

Согласно документации:

Ожидаемое количество записей на карте и коэффициент загрузки должны учитываться при настройке ее начальной емкости, чтобы минимизировать количество операций перефразировки. Если начальная емкость больше, чем максимальное количество записей, деленное на коэффициент загрузки, операции перефразировки никогда не будут выполняться. https://docs.oracle.com/javase/8/docs/api/java/util/HashMap.html

0 голосов
/ 21 мая 2019

Самый простой способ проверить такое поведение - взглянуть на исходный код openjdk. Это все свободно доступно и относительно легко читается.

В этом случае, отметив HashMap , вы увидите, что есть некоторые подробные замечания по реализации, которые объясняют, как работает определение размера, какой коэффициент загрузки используется в качестве порога (который определяет поведение, которое вы видите), и даже как принято решение, использовать ли деревья для мусорного ведра. Прочитайте это и возвращайтесь, если не ясно.

Код довольно хорошо оптимизирован с расширением очень дешевой операции. Я предлагаю использовать профиль, чтобы получить некоторые доказательства того, что проблема с производительностью связана с расширением, прежде чем делать какие-либо настройки.

...