Как превратить массив в ArrayList в Java: 4 способа с примерами

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Превращаем массив в ArrayList: почему это вечная головная боль Java-разработчика

Каждый, кто хоть раз писал на Java, сталкивался с ситуацией: у вас есть готовый массив String[] или int[], а по задаче нужен гибкий ArrayList с его методами add(), remove() и динамическим размером. Вроде бы мелочь, но именно этот вопрос на Stack Overflow собрал десятки тысяч просмотров и кучу голосов. Почему? Потому что, как часто бывает в Java, есть «очевидное» решение, которое таит подводные камни.

В этой статье мы не просто дадим готовый код. Мы пройдёмся по всем способам создания ArrayList из массива в Java, разберём их плюсы и минусы, производительность и, самое главное, — когда какой вариант использовать. После прочтения вы сможете уверенно выбрать правильный инструмент под свою задачу и не нарваться на UnsupportedOperationException в самый неожиданный момент.

Поехали! (или как говорят джависты — let's dive into the code)

Способ 1: Классика — Arrays.asList()

Самый популярный и короткий способ. Вы наверняка его видели:

String[] fruits = {"apple", "banana", "cherry"};
List<String> fruitList = Arrays.asList(fruits);

Выглядит красиво, да? Но есть нюанс. Метод Arrays.asList() возвращает не java.util.ArrayList, а свою внутреннюю статическую версию — java.util.Arrays.ArrayList. Это фиксированный список, который не поддерживает операции изменения размера. Если вы попытаетесь сделать fruitList.add("date"), получите UnsupportedOperationException.

Плюсы:

  • Максимально короткий и читаемый код.
  • Работает как мост между массивом и API коллекций.
  • Изменения в списке отражаются на исходном массиве (и наоборот).

Минусы:

  • Фиксированный размер — нельзя добавлять или удалять элементы.
  • Возвращаемый список — это «обёртка» над массивом, а не полноценный ArrayList.

Когда использовать: Когда вам нужен список только для чтения, или когда вы точно знаете, что размер меняться не будет. Например, для передачи в метод, который принимает List<?> и не модифицирует его.

Как получить полноценный ArrayList из Arrays.asList()?

Просто оберните результат в конструктор:

String[] fruits = {"apple", "banana", "cherry"};
ArrayList<String> fruitList = new ArrayList<>(Arrays.asList(fruits));
fruitList.add("date"); // Теперь работает без ошибок

Этот приём — золотая середина. Вы используете короткую запись Arrays.asList, но получаете полноценную динамическую коллекцию.

Способ 2: Collections.addAll() — скорость и контроль

Если вы гонитесь за производительностью или просто хотите избежать двойного копирования (сначала в список фиксированного размера, потом в ArrayList), есть метод Collections.addAll():

String[] fruits = {"apple", "banana", "cherry"};
ArrayList<String> fruitList = new ArrayList<>(fruits.length);
Collections.addAll(fruitList, fruits);

Что здесь происходит? Мы сразу создаём ArrayList с нужным начальным размером (чтобы избежать лишних перестроений внутреннего массива), а затем за один проход копируем все элементы. Метод addAll работает быстрее, чем цикл for, так как вызывает System.arraycopy() на низком уровне.

Плюсы:

  • Высокая скорость — практически на уровне прямого копирования памяти.
  • Сразу получаем полноценный ArrayList с возможностью изменений.
  • Можно заранее задать ёмкость списка.

Минусы:

  • Код чуть длиннее, чем Arrays.asList().
  • Требует импорта java.util.Collections.

Когда использовать: Когда важна производительность (например, большие массивы данных) или когда вы создаёте ArrayList и тут же наполняете его данными. Это предпочтительный способ для production-кода.

Способ 3: Stream API — современный и гибкий

Java 8 принесла нам Stream API, и с тех пор многие задачи стали решаться в функциональном стиле. Создание ArrayList из массива — не исключение:

String[] fruits = {"apple", "banana", "cherry"};
ArrayList<String> fruitList = Arrays.stream(fruits)
                                    .collect(Collectors.toCollection(ArrayList::new));

Или, если вам нужен список именно ArrayList, а не общий List:

ArrayList<String> fruitList = Arrays.stream(fruits)
                                    .collect(Collectors.toCollection(ArrayList::new));

Обратите внимание: Collectors.toList() не гарантирует, что вернёт именно ArrayList (может быть другой имплементация). Поэтому лучше использовать toCollection(ArrayList::new).

Плюсы:

  • Огромная гибкость — на лету можно фильтровать, маппить, сортировать данные.
  • Код выглядит современно и лаконично (если вы любите функциональщину).
  • Легко комбинировать с другими stream-операциями.

Минусы:

  • Чуть медленнее, чем Collections.addAll() из-за накладных расходов на стримы.
  • Может быть избыточным для простого копирования.

Когда использовать: Когда вам нужно не просто скопировать массив, а ещё и обработать данные (отфильтровать null, преобразовать строки, убрать дубликаты). Stream API — ваш друг.

Способ 4: Ручное копирование — старый добрый цикл

Иногда, чтобы понять магию, нужно написать всё руками. Для примитивных типов (int[], double[]) это вообще единственный прямой способ, так как Arrays.asList() не работает с примитивами корректно (он создаёт список из одного элемента — самого массива).

int[] numbers = {1, 2, 3, 4, 5};
ArrayList<Integer> numberList = new ArrayList<>(numbers.length);
for (int num : numbers) {
    numberList.add(num);
}

Для массивов объектов (String[]) этот способ тоже работает, но он самый медленный и многословный. Однако он даёт полный контроль над процессом.

Плюсы:

  • Полный контроль — можно добавить логику проверки, трансформации.
  • Понятен новичкам, не требует знания API коллекций.
  • Работает с примитивами.

Минусы:

  • Медленнее всех остальных способов.
  • Много boilerplate

Блоги

Рекомендаций по книгам