Можно ли хранить примитивные типы (int, long) в ArrayList?

«Можно ли хранить примитивные типы (int, long) в ArrayList?» — вопрос из категории Java Core, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Непосредственно — нет. Стандартный ArrayList<T> (как и все дженерики в Java) работает только с ссылочными типами (объектами). Примитивные типы (int, long, boolean и т.д.) не могут быть параметром типа.

Почему? Дженерики в Java реализованы через стирание типов (type erasure), и во время выполнения информация о типе T теряется, заменяясь на Object. Примитивы не являются подтипами Object.

Решение 1: Автоупаковка (Autoboxing) Java автоматически конвертирует примитив в соответствующий класс-обертку (например, int -> Integer). Это позволяет «хранить» примитивы в ArrayList<Integer>.

ArrayList<Integer> list = new ArrayList<>();
list.add(42); // Автоупаковка: int 42 преобразуется в Integer
int value = list.get(0); // Автораспаковка: Integer преобразуется обратно в int

Недостаток: Нагрузка на память и производительность из-за создания объектов-оберток и операций упаковки/распаковки.

Решение 2: Специализированные библиотеки Для высокопроизводительных сценариев используйте структуры, работающие непосредственно с примитивами:

  • Trove (например, TIntArrayList)
  • Eclipse Collections (например, IntArrayList)
  • fastutil (например, IntArrayList)

Пример с Eclipse Collections:

IntArrayList primitiveList = IntLists.mutable.empty();
primitiveList.add(42); // Работает напрямую с int
int value = primitiveList.get(0); // Прямой доступ

Эти библиотеки экономят память и повышают скорость за счет отсутствия упаковки.