Ответ 1
В Autoboxing используется Integer.valueOf
, который внутренне кэширует объекты Integer для небольших целых чисел (по умолчанию от -128 до 127, но максимальное значение может быть сконфигурировано с помощью свойства "java.lang.Integer.IntegerCache.high" - см. источник код Integer.valueOf), поэтому он отличается от прямого вызова new Integer
. Поскольку Integer.valueOf
выполняет быструю проверку величины целочисленного значения перед вызовом new Integer
, он немного быстрее вызывает new Integer
напрямую (хотя он использует больше памяти, если у вас много маленьких целых чисел). Распределение на Java очень быстро, и время выполнения GC пропорционально количеству живых короткоживущих объектов (т.е. Не пропорционально количеству мусора), поэтому GC также очень быстро.
Но в зависимости от версии JVM и оптимизации которой существует оптимизация скалярной замены, которая может привести к значительно большей разнице в производительности при распределении короткоживущих объектов (в вашем примере оптимизация не может быть выполнена, поскольку вы сохраняете объекты на карте, но во многих других ситуациях это полезно).
В последних версиях JVM существует оптимизация скалярной замены (кроме 1.6.0_18, где escape-анализ временно отключено), что означает, что выделение короткоживущих объектов может быть оптимизировано. Когда скалярная замена в JVM была новой, кто-то сделал тест, где был код, похожий на ваш. В результате код, который использовал примитивы, был самым быстрым, код с явными вызовами new Integer()
был почти таким же быстрым, как и тот, который использовал примитивы, а код, который использовал автобоксинг, был намного медленнее. Это объясняется тем, что autoboxing использует Integer.valueOf
и, по крайней мере, тогда оптимизация скалярной замены не учитывала этот особый случай. Я не знаю, улучшена ли оптимизация с тех пор.