Преобразование массива в List и обратно - Вопросы

Всего: 6 вопросов

1. 

Почему Arrays.asList(intArray) возвращает список из одного элемента?

Метод объявлен как Arrays.asList(T... a), а параметр типа T может быть только ссылочным типом. Массив int[] сам является объектом, поэтому компилятор передаёт его как один varargs-аргумент и выводит тип результата List<int[]> размером 1, а не List<Integer> из трёх элементов.

int[] numbers = {1, 2, 3};

// Неправильно: список из ОДНОГО элемента — самого массива
List<int[]> wrong = Arrays.asList(numbers);
System.out.println(wrong.size()); // 1

// Правильно: сначала распаковываем поток
List<Integer> right = Arrays.stream(numbers).boxed().toList();
System.out.println(right.size()); // 3

Для массива объектов (Integer[], String[]) Arrays.asList() действительно даёт список из всех элементов, но этот список имеет фиксированный размер: add() и remove() бросят UnsupportedOperationException.

2. 

Как преобразовать массив int[] в List<Integer> и чем Stream.toList() отличается от collect(Collectors.toList())?

Преобразование делается в три шага: Arrays.stream() создаёт IntStream, boxed() упаковывает каждый int в Integer, а терминальная операция собирает результат в список.

int[] numbers = {1, 2, 3, 4, 5};

// Изменяемый список
List<Integer> list = Arrays.stream(numbers)
                           .boxed()
                           .collect(Collectors.toList());

// Java 16+: короче, но список неизменяемый
List<Integer> immutable = Arrays.stream(numbers).boxed().toList();

Stream.toList() появился в Java 16 и всегда возвращает неизменяемый список (допускающий null): add() или set() выбросят UnsupportedOperationException. Коллектор Collectors.toList() возвращает изменяемый список, на практике ArrayList, но конкретная реализация спецификацией не гарантируется.

3. 

Как преобразовать List<Integer> обратно в массив int[] и чем это опасно при наличии null?

Обратное преобразование зеркально прямому: mapToInt() распаковывает каждый Integer в int, а toArray() собирает примитивный массив.

List<Integer> list = List.of(10, 20, 30, 40);

int[] array = list.stream()
                  .mapToInt(Integer::intValue)
                  .toArray();

System.out.println(Arrays.toString(array)); // [10, 20, 30, 40]

Тот же код работает и для ArrayList<Integer>, потому что ArrayList — это List. Вариант list.toArray(new int[0]) не компилируется: toArray() работает только с массивами объектов. Если в списке может оказаться null, распаковка упадёт с NullPointerException — отфильтруйте значения заранее через .filter(Objects::nonNull).

4. 

Чем различаются int[], Integer[] и List<Integer> и как преобразовать их друг в друга?

int[] — массив примитивов, Integer[] — массив объектов-обёрток, List<Integer> — коллекция этих обёрток. Это три несовместимых типа: присваивание int[] a = integerArray; не компилируется, каждая пара требует явного преобразования.

// int[] -> Integer[]
int[] primitives = {1, 2, 3};
Integer[] boxed = Arrays.stream(primitives)
                        .boxed()
                        .toArray(Integer[]::new);

// Integer[] -> int[]
Integer[] source = {4, 5, 6};
int[] unboxed = Arrays.stream(source)
                      .mapToInt(Integer::intValue)
                      .toArray();

// Integer[] -> изменяемый List<Integer>
List<Integer> list = new ArrayList<>(Arrays.asList(source));

// List<Integer> -> Integer[]
Integer[] back = list.toArray(new Integer[0]);

Обратите внимание: Arrays.asList(source) для Integer[] действительно даёт список из трёх элементов, потому что это массив объектов. С int[] тот же код ведёт себя иначе.

5. 

Как преобразовать массив int[] именно в ArrayList<Integer>, а не просто в List?

List — это интерфейс, и конкретная реализация за ним спецификацией не гарантируется. Если по сигнатуре метода нужен именно ArrayList<Integer>, попросите его явно — через коллектор Collectors.toCollection(ArrayList::new) или обернув готовый список.

int[] numbers = {1, 2, 3, 4, 5};

// Вариант 1: собрать сразу в ArrayList
ArrayList<Integer> arrayList = Arrays.stream(numbers)
        .boxed()
        .collect(Collectors.toCollection(ArrayList::new));

// Вариант 2: обернуть готовый список
ArrayList<Integer> copy = new ArrayList<>(list);

arrayList.add(6); // работает, размер не фиксирован

Оба варианта дают полноценный изменяемый ArrayList, в который можно добавлять и из которого можно удалять элементы — в отличие от результата Stream.toList() и от списка из Arrays.asList().

6. 

Как преобразовать массив не в List, а в другую коллекцию — например в Set<Integer> или LinkedList<Integer>?

В приёме нет ничего специфичного для List: меняется только коллектор. Связка Arrays.stream(arr).boxed() остаётся прежней, а Collectors.toSet() или Collectors.toCollection(...) задают нужную реализацию Collection.

int[] numbers = {3, 1, 2, 3};

// int[] -> Set<Integer> (дубликаты отбрасываются)
Set<Integer> set = Arrays.stream(numbers).boxed().collect(Collectors.toSet());

// int[] -> LinkedList<Integer>
LinkedList<Integer> linked = Arrays.stream(numbers)
        .boxed()
        .collect(Collectors.toCollection(LinkedList::new));

// любая Collection<Integer> -> int[]
int[] fromSet = set.stream().mapToInt(Integer::intValue).toArray();

Обратное преобразование одинаково для всех коллекций: stream().mapToInt(Integer::intValue).toArray(). А для массива объектов шаг упаковки не нужен вовсе: List<String> words = new ArrayList<>(Arrays.asList(stringArray));.

Страница 1 из 1