Чем int[] на миллион чисел выгоднее List<Integer> того же размера?
int[] — сплошной блок ~4 МБ. List<Integer> — миллион отдельных объектов Integer (16 байт каждый) плюс массив ссылок: в 4–5 раз больше памяти, нагрузка на GC и промахи кэша при обходе.
- Каждая упаковка вне кэша −128…127 — аллокация
- Примитивные стримы: IntStream вместо Stream<Integer>
- Библиотеки примитивных коллекций: fastutil, Eclipse Collections
А ещё Valhalla (value-классы) должна снять проблему
Подробно
Каждый бокс — это аллокация объекта в куче и лишняя косвенность. На больших структурах это бьёт по памяти и скорости. Поэтому в перфо-чувствительном коде берут примитивные массивы вместо List<Integer> и специализированные потоки (IntStream/LongStream/DoubleStream) вместо Stream<Integer> — они не боксят элементы. Integer-кэш покрывает только -128..127, на больших значениях не помогает.
Что хотят услышать
- Размещение в памяти.
- Последствия для GC и кэша.
- Альтернативы.
Частые ошибки
- Полагать, что JIT уберёт боксинг из List<Integer>.
- Рассчитывать на Integer cache для произвольных значений.
Проверьте себя
Один верный вариант. Подумайте, потом откройте ответ.
Показать варианты и ответ
- ✗Разницы нет: JIT всё равно разбоксит List<Integer> в массив примитивов
- ✗List<Integer> быстрее, потому что Integer кэшируется для всех значений
- ✓int[] — сплошные ~4 МБ без боксинга; список хранит миллион объектов Integer
- ✗int[] медленнее: примитивы хранятся в куче по одному объекту, а список — сплошным блоком
Что спросят дальше
- Чем IntStream лучше Stream<Integer>?
- Когда удобство List<Integer> важнее экономии памяти?
Разбор темы
- Примитивы, обёртки и Integer cache
Восемь примитивов и их диапазоны, autoboxing, кэш Integer и ловушка ==, NPE при распаковке и цена боксинга.
Связанные вопросы
Разбор собеседования с sotto
После собеседования sotto разбирает разговор: оценка, каждый вопрос — хорошо, частично или слабо, чего не хватило в ответе и над чем поработать к следующему разу. Первые 30 минут бесплатно.