JavaRush /Java блог /Random UA /Java list to array: перетворюємо список елементів на маси...
Анзор Кармов
31 рівень
Санкт-Петербург

Java list to array: перетворюємо список елементів на масив

Стаття з групи Random UA
Вітання! У цій статті ми розглянемо, як Java перетворювати список елементів в масив елементів. Власне, способів зробити це не так багато, і всі вони прості, так що стаття буде нескладною. Java list to array: перетворюємо список елементів на масив - 1Відразу ж визначимося, із чим ми працюємо. Конвертуватимемо списки в масиви, а конкретніше — список рядків: I, love, learning, on, JavaRush будемо перетворювати на масив таких же рядків. Але спочатку маленький бонус. Розкажемо про те, як швидко запиляти списочок.

Як по швидкому запиляти списочок list to array

Запам'ятай: у цьому житті є два сценарії. Перший - цілковита туга і нудьга, коли ми ініціалізуємо новий список:
List<String> wordsList = new ArrayList();
А потім додаємо до нього значення... По одному...
wordsList.add("I");
wordsList.add("love");
wordsList.add("learning");
wordsList.add("on");
wordsList.add("JavaRush");
Нікуди не годиться. Вже забув, навіщо потрібний був список, поки його створював! Другий шлях — відсікання всього зайвого та прийняття... класів утиліт. Наприклад, класу Arrays, в якому є неймовірно зручний метод asList. У нього можна передавати все, що хочеш зробити списком, і метод зробить це списком. Ось приблизно так:
List<String> wordsList = Arrays.asList("I", "love", "learning", "on", "JavaRush");
Даний метод бере в себе varargs- у певному сенсі масив. Перепрошую за те, що в лекції під назвою list to array я навчив тебе спочатку array to list, але того вимагали обставини. Ну а тепер до наших методів переведення списків до масивів.

Спосіб №1. Перебір

Спосіб відмінно підійде тим, хто любить не надто вдумливо набирати код на клавіатурі. Свого роду медитація. Крок 1. Створюємо масив такої ж довжини, як і список:
List<String> wordsList = Arrays.asList("I", "love", "learning", "on", "JavaRush");
String[] wordsArray = new String[wordsList.size()];
Крок 2. Створюємо цикл з лічильником, щоб пробігтися всіма елементами списку і мати можливість звертатися до осередків масиву за індексом:
for (int i = 0; i < wordsList.size(); i++) {

}
Крок 3. Усередині циклу значення кожного елемента списку з індексом i присвоюємо осередку масиву з індексом i:
for (int i = 0; i < wordsList.size(); i++) {
    wordsArray[i] = wordsList.get(i);
}
Підсумок:
public static void main(String[] args) {

        List<String> wordsList = Arrays.asList("I", "love", "learning", "on", "JavaRush");
        String[] wordsArray = new String[wordsList.size()];

        for (int i = 0; i < wordsList.size(); i++) {
            wordsArray[i] = wordsList.get(i);
        }
    }

Спосіб №2. Метод доArray

Напевно, найоптимальніша у використанні штуковина. В інтерфейсі Listє два методи toArray, які з поточного списку створюють масив:
Object[] toArray();
 T[] toArray(T[] a);
Перший метод повертає масив об'єктів, в якому розташовані всі елементи поточного списку (від першого до останнього):
public class Main {
    public static void main(String[] args) {
        List<String> wordsList = Arrays.asList("I", "love", "learning", "on", "JavaRush");
        String[] wordsArray = (String[]) wordsList.toArray();

        for (String word : wordsArray) {
            System.out.println(word);
        }

    }
}
Запустимо метод mainі побачимо наступне:

I
love
learning
on
JavaRush
Однак цей метод має особливість: він завжди повертає масив об'єктів (Object[]). Тому результат, що повертається, необхідно привести до потрібного типу даних. У прикладі вище ми привели його до масиву рядків (String[]). Проте цей метод не приймає аргументів, що в деяких ситуаціях може бути зручно. Другий метод також повертає масив, де розташовані всі елементи поточного списку (від першого до останнього). Однак на відміну від першого, другий метод приймає як аргумент масив певного типу. Але і результатом роботи другого методу буде не масив об'єктів, а масив певного типу даних такого ж, як і тип даних у переданому в аргументи методі масиву.
public class Main {
    public static void main(String[] args) {
        List<String> wordsList = Arrays.asList("I", "love", "learning", "on", "JavaRush");
        String[] wordsArray = wordsList.toArray(new String[0]);

        for (String word : wordsArray) {
            System.out.println(word);
        }

    }
}
Якщо запустити метод main, у висновку ми побачимо ті самі слова:

I
love
learning
on
JavaRush
Поговоримо трохи про масив, який передається як аргумент методу toArray. Логіка роботи методу залежить від довжини масива, що передається. Є три можливі сценарії:

1. Довжина маси, що передається, менша, ніж довжина списку

У цьому випадку метод створює новий масив і поміщає до нього елементи списку. Ми продемонстрували це на прикладі вище.

2. Довжина елемента, що передається, дорівнює довжині списку

Метод помістить елементи списку переданий масив. Продемонструємо це:
public class Main {
    public static void main(String[] args) {
        List<String> wordsList = Arrays.asList("I", "love", "learning", "on", "JavaRush");

        // Создаем пустой массив нужной длины
        String[] array = new String[wordsList.size()];

        // Отправляем пустой массив в метод toArray
        wordsList.toArray(array);

        // Проверяем, заполнился ли наш массив. Спойлер: да
        for (String word : array) {
            System.out.println(word);
        }

    }
}
При виведенні ми побачимо ті самі рядки, і стане ясно, що метод заповнив створений нами масив.

3. Довжина маси, що передається, більша, ніж довжина списку

Метод запише всі елементи списку масив, а наступну за останнім доданим елементом комірку запише значення null. Продемонструємо це:
public class Main {
    public static void main(String[] args) {
        List<String> wordsList = Arrays.asList("I", "love", "learning", "on", "JavaRush");

        // Создаем пустой массив, длина которого в 2 раза больше длины списка
        String[] array = new String[wordsList.size() * 2];

        for (int i = 0; i < array.length; i++) {
            // В каждую ячейку запишем строковое представление текущего индекса
            array[i] = String.valueOf(i);
        }

        // Отправляем массив в метод toArray
        wordsList.toArray(array);

        // Проверяем, что лежит в нашем массиве
        for (String word : array) {
            System.out.println(word);
        }

    }
}
Після запуску методу mainв консолі побачимо таке:

I
love
learning
on
JavaRush
null
6
7
8
9
Який же метод із трьох вибрати? У ранніх версіях Java було оптимально передавати масив з довжиною, що дорівнює довжині списку або більше за неї. Однак у сучасних JVM є оптимізації, і в деяких випадках вони забезпечують більш швидку роботу методу, який передається масив меншої довжини, ніж довжина списку. Так що якщо ви працюєте на сучасній версії Java, передавайте метод порожній масив, як ми робабо в першому прикладі:
wordsList.toArray(new String[0]);

Спосіб №3. Stream API

Даний спосіб підійде тим, хто хоче не просто перевести список у масив, але й принагідно вирішити пару трійку інших завдань. А ще – людям, знайомим із Java Stream API. На JavaRush є непогана стаття на цю тему . У цьому розділі ми розберемо кілька прикладів з використанням стриму. Як за допомогою стриму привести список до масиву:
public class Main {
    public static void main(String[] args) {
        List<String> wordsList = Arrays.asList("I", "love", "learning", "on", "JavaRush");

        String[] strings = wordsList.stream()
                .toArray(String[]::new);

        for (String s : strings) {
            System.out.println(s);
        }

        /*
        Output:
        I
        love
        learning
        on
        JavaRush

         */
    }
}
Але якщо вам просто потрібно привести список до масиву, краще зробити це за допомогою методу toArray, описаному в розділі Спосіб №2. А от якщо ви хочете не просто привести список до масиву, а ще й зробити деяку дію над кожним елементом, тоді вам за адресаою. Спробуємо привести список до масиву так, щоб у підсумковому масиві всі рядки були записані у верхньому регістрі:
public class Main {
    public static void main(String[] args) {
        List<String> wordsList = Arrays.asList("I", "love", "learning", "on", "JavaRush");

        String[] strings = wordsList.stream()
                .map(str -> str.toUpperCase())
                .toArray(String[]::new);

        for (String s : strings) {
            System.out.println(s);
        }

        /*
            Output:
            I
            LOVE
            LEARNING
            ON
            CODEGYM

         */
    }
}
Тут .map(str -> str.toUpperCase())ми визначабо, що потрібно зробити з кожним рядком у списку. В даному випадку ми вирішабо перетворювати кожен рядок у верхній регістр, а потім збирати його на масив. Використання Stream API дозволяє не тільки перетворювати кожне значення, а й фільтрувати їх. Припустимо, ми хочемо зі списку рядків зібрати масив, але таким чином, щоб у масив потрапабо лише рядки завдовжки більше двох символів:
public class Main {
    public static void main(String[] args) {
        List<String> wordsList = Arrays.asList("I", "love", "learning", "on", "JavaRush");

        String[] strings = wordsList.stream()
                .filter(str -> str.length() > 2)
                .map(str -> str.toUpperCase())
                .toArray(String[]::new);

        for (String s : strings) {
            System.out.println(s);
        }

        /*
            Output:
            LOVE
            LEARNING
            CODEGYM
         */
    }
}
Тут у рядку .filter(str -> str.length() > 2)ми створабо так званий фільтр, який застосовуватиметься до кожного елемента списку, перш ніж він потрапить до масиву. В даному випадку у кожного рядка викликається метод length(), і якщо результат виразу str.length() > 2істинний, такий рядок потрапить у результуючу вибірку, а в результаті масив. Інакше не потрапить. Тут, мабуть, варто сказати, що цього можна домогтися, просто перебираючи елементи і накладаючи різні обмеження. Можна робити й так. Stream API надає більш функціональний підхід для вирішення таких завдань.

Підсумки

У цій статті ми розглянули різні способи приведення списків до масивів:
  • простий перебір;
  • методtoArray;
  • Stream API.
Найоптимальніший варіант - використовувати метод toArray, визначений в інтерфейсі List. Таких методів два:
  • Object[] toArray();
  • T[] toArray(T[] a);
Перший не приймає аргументи, але повертає масив об'єктів, через що найчастіше доведеться вдаватися до явного приведення типів. Другий повертає масив потрібного типу, але як аргумент приймає масив. Найкраще передавати порожній масив у метод, і буде вам щастя. Використання Stream API дозволяє не тільки привести список до масиву, але й принагідно провести деякі дії, наприклад відфільтрувати або перетворити елементи, перед додаванням їх до масиву.

Домашка

Спробуйте повторити всі приклади цієї статті самостійно, тільки замість вихідного списку рядків використовуйте список цілих чисел від 0 до 10. Природно, деякі умови з прикладів, що застосовуються тільки для рядків, вам доведеться адаптувати під нові умови.
Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ