Как преобразовать List в массив в Java
Преобразуйте Java List в массив с помощью toArray и подходов на основе stream.
List и массив хранят одни и те же элементы, но предоставляют разные API: List изменяет размер и имеет богатый набор методов, тогда как массив имеет фиксированную длину и используется многими старыми или низкоуровневыми API. Преобразование из одного в другое — это однострочная операция в современной Java; единственный реальный выбор — какой вариант лучше читается и нужен ли вам массив объектов или примитивов. На этой странице рассматривается типизированная перегрузка toArray, ссылка на конструктор в Java 11+, путь через stream для примитивных массивов и подводные камни безаргументного toArray().
Идиоматический способ: toArray с типизированным массивом
List.toArray(T[]) возвращает строго типизированный массив. Передайте массив нулевой длины нужного типа элемента и позвольте JDK самому определить размер результата:
List<String> names = List.of("Ann", "Bob", "Cy");
String[] arr = names.toArray(new String[0]);Аргумент new String[0] передаёт тип (String[]), а не предварительно заданный буфер. На современных JVM форма с пустым массивом является рекомендуемой — она такая же быстрая, как массив точно заданного размера, и позволяет избежать ошибки, при которой слишком маленький массив перевыделяется, а слишком большой оставляет хвостовые null. Используйте этот подход всякий раз, когда вам нужен массив объектного типа, например String[], Integer[] или ваш собственный класс.
Форма Java 11+: ссылка на конструктор массива
Начиная с Java 11 можно передавать ссылку на конструктор массива вместо буквального пустого массива. Это выражает именно то, что имеется в виду — «сделай мне String[]»:
String[] arr = names.toArray(String[]::new);Это компилируется в то же самое, что и new String[0], но читается понятнее. Обратите внимание: безаргументный toArray() — это ловушка: он всегда возвращает Object[], но не String[], поэтому приведение его результата к String[] бросает ClassCastException во время выполнения.
| Подход | Тип результата | Примечания |
|---|---|---|
list.toArray(new String[0]) | String[] | Рекомендуется для массивов объектов |
list.toArray(String[]::new) | String[] | Java 11+, наиболее понятная форма |
list.toArray() | Object[] | Теряет тип элемента; редко то, что нужно |
list.stream().mapToInt(...).toArray() | int[] | Единственный способ получить примитивный массив |
Примитивные массивы получают через stream
toArray может производить только массивы объектов. List<Integer> нельзя напрямую преобразовать в int[] — автоупаковка не распространяется на массивы. Используйте stream для распаковки каждого элемента:
List<Integer> nums = List.of(10, 20, 30);
int[] prim = nums.stream().mapToInt(Integer::intValue).toArray();Тот же паттерн даёт вам long[] (mapToLong) и double[] (mapToDouble). В JDK нет специального сокращения для примитивных массивов, поэтому stream — это идиоматический путь.
Практический пример
Эта программа запускает все подходы параллельно, выводит тип времени выполнения, который на самом деле возвращает безаргументный toArray, и доказывает, что полученный массив является независимой копией — его редактирование не затрагивает исходный список.
Что можно извлечь из запуска:
toArray(new String[0])иtoArray(String[]::new)оба выводят[Ann, Bob, Cy]— это два способа записи одного и того же типизированного преобразования, и вы можете выбрать тот, который лучше читается в вашем коде.- Безаргументный
toArray()сообщает свой тип времени выполнения какObject[], а неString[]— наглядное доказательство того, что он стирает тип элемента, и почему следует избегать приведения его результата. List<Integer>становится настоящимint[]только послеmapToInt; выведенный[10, 20, 30]является примитивным массивом, а неInteger[], поэтому никакой упаковки не остаётся.Arrays.stream(prim).sum()выводит60, подтверждая, что результат является пригодным для использования примитивным массивом, который можно сразу передавать в числовые операции stream.- После
a1[0] = "ZZ"массив выводит[ZZ, Bob, Cy], тогда как список по-прежнему выводит[Ann, Bob, Cy]—toArrayвозвращает независимую копию, поэтому изменения массива никогда не попадают обратно в исходный список.