Java: конвертируем поток в массив

Вступление

В этом уроке мы будем конвертировать поток в массив как для простых типов, так и объектов.

Stream.toArray()

Метод toArray() – это встроенный метод из класса Stream, который действительно удобно использовать при преобразовании из потока в массив. Это работает как с простыми типами, так и с объектами, хотя есть небольшая разница в использовании.

Метод возвращает новый массив, это значит, что мы будем упаковывать результаты в новый массив. Для объектов нам нужно будет указать тип, а также предоставить методу конструктор массива этого типа.

Простые типы

В Java 8 есть специальные потоки для примитивных типов: IntStream, LongStream и DoubleStream. Используем IntStream для хранения диапазона целых чисел, а затем преобразуем его в массив:

IntStream stream = IntStream.range(10, 20);
int[] array = stream.toArray();
System.out.println("Printing array ...");

for (int i = 0; i < array.length; ++i)
    System.out.print(array[i] + " ");

Результат:

Printing array ...
10 11 12 13 14 15 16 17 18 19 

Потоки удобны для обработки данных, поэтому вам может потребоваться выполнить предварительную обработку потока, а не массива, и в конце преобразовать его в один:

IntStream stream = IntStream.range(10, 20);
int[] array = stream.filter(x -> x%2 == 0).toArray();
System.out.println("\nPrinting even numbers ...");
for (int i = 0; i < array.length; ++i)
    System.out.print(array[i] + " ");

Результат:

Printing even numbers ...
10 12 14 16 18

Объекты

Для объектов метод toArray() принимает ссылку на конструктор массива для соответствующего объекта и возвращает массив этого типа. Создадим поток строковых объектов и преобразуем его в массив:


List<String> list = new ArrayList<>();
list.add("John");
list.add("Jenny");
list.add("Martha");


Stream<String> stream = list.stream();


String[] array = stream.toArray(String[]::new);
System.out.println("Printing String array ...");
for (int i = 0; i < array.length; ++i)
    System.out.println(array[i]);

Результат:

Printing String array...
John
Jenny
Martha

Примечание: Метод toArray() требует использования конструктора массива, и мы использовали ссылку на метод, чтобы указать тип String[]::new. toArray() возвращает массив указанного типа, и если тип не указан, произойдет несоответствие:

String[] array = stream.toArray();

В результате ошибка:

error: incompatible types: Object[] cannot be converted to String[]

Вместо ссылок на сокращённые методы мы можем использовать для этого лямбда-выражения. Давайте отфильтруем только имена, начинающиеся на “J”:

List<String> list = new ArrayList<>();
list.add("John");
list.add("Jenny");
list.add("Martha");


Stream<String> stream = list.stream();


String[] array = stream
        .filter(string -> string.startsWith("J"))
        .toArray(size -> new String[size]);
System.out.println("Printing names starting with 'J'...");
for (int i = 0; i < array.length; ++i)
    System.out.println(array[i]);

Вывод:

Printing names starting with 'J'...
John
Jenny

Заключение

В этой статье мы преобразовали поток в массив. Это можно сделать для массивов и объектов с помощью метода Stream.toArray(), хотя и с несколько иным использованием.

Ответить