Как преобразовать поток Java 8 в массив?

776

Какой самый простой / короткий способ конвертировать Java 8 Streamв массив?

MC Emperor
источник
2
Я бы посоветовал вам отменить откат, поскольку вопрос был более полным и показал, что вы что-то пробовали.
Скиви
2
@skiwi Спасибо! но я думал, что попытка кода на самом деле не добавляет больше информации к вопросу, и никто еще не кричал «покажи нам свою попытку» =)
17
@skiwi: Хотя я обычно кричу на вопросы «сделай домашнее задание вместо меня», этот конкретный вопрос кажется мне более понятным без какого-либо дополнительного беспорядка. Давайте держать это в порядке.
Хонза Зидек
Вы можете найти много ответов и рекомендаций в официальных документах пакета: docs.oracle.com/javase/8/docs/api/java/util/stream/…
Кристоф Русси,

Ответы:

1169

Самый простой способ - использовать toArray(IntFunction<A[]> generator)метод со ссылкой на конструктор массива. Это предлагается в документации API для метода .

String[] stringArray = stringStream.toArray(String[]::new);

Что он делает, так это находит метод, который принимает целое число (размер) в качестве аргумента и возвращает a String[], что и делает (одна из перегрузок) new String[].

Вы также можете написать свой собственный IntFunction:

Stream<String> stringStream = ...;
String[] stringArray = stringStream.toArray(size -> new String[size]);

Цель IntFunction<A[]> generator- преобразовать целое число, размер массива, в новый массив.

Пример кода:

Stream<String> stringStream = Stream.of("a", "b", "c");
String[] stringArray = stringStream.toArray(size -> new String[size]);
Arrays.stream(stringArray).forEach(System.out::println);

Печать:

a
b
c
skiwi
источник
8
и вот объяснение, почему и как на самом деле работает ссылка на конструктор Array: stackoverflow.com/questions/29447561/…
jarek.jpa
"Zenexer прав, решение должно быть: stream.toArray (String [] :: new);" ... Хорошо, но нужно понимать, что ссылка на метод логически и функционально эквивалентна, toArray(sz -> new String[sz])так что я не уверен, что кто-то действительно может сказать, какое решение должно или должно быть.
Скотт
3
@scottb sz -> new String[sz]создает новую функцию, а ссылка на конструктор - нет. Я думаю, это зависит от того, насколько ты ценишь отток мусора.
WORMSS
3
@ WORMSS Это не так. Он (статически!) Создает новый private метод , который не может вызвать отток, и обе версии должны создать новый объект. Ссылка создает объект, который указывает непосредственно на целевой метод; лямбда создает объект, который указывает на сгенерированный private. Ссылка на конструктор все равно должна работать лучше из-за отсутствия косвенности и более легкой оптимизации виртуальной машины, но отток не имеет к этому никакого отношения.
HTNW
2
@HTNW вы правы, мои извинения. Это была моя попытка отладки, которая привела к оттоку, который вызвал отток, когда я впервые попытался сделать это, так что у меня застряло в голове, что это так. (Ненавижу, когда это происходит).
WORMSS
41

Если вы хотите получить массив потоков со значениями от 1 до 10 из потока, в вашем распоряжении есть IntStream.

Здесь мы создаем Stream с помощью метода Stream.of и конвертируем Stream в IntStream, используя mapToInt. Затем мы можем вызвать метод toStray от IntStream.

Stream<Integer> stream = Stream.of(1,2,3,4,5,6,7,8,9,10);
//or use this to create our stream 
//Stream<Integer> stream = IntStream.rangeClosed(1, 10).boxed();
int[] array =  stream.mapToInt(x -> x).toArray();

Здесь то же самое, без потока, используя только IntStream

int[]array2 =  IntStream.rangeClosed(1, 10).toArray();
Ида Бучич
источник
16

Вы можете преобразовать поток Java 8 в массив, используя этот простой блок кода:

 String[] myNewArray3 = myNewStream.toArray(String[]::new);

Но давайте объясним подробнее, во-первых, давайте создадим список строк, заполненный тремя значениями:

String[] stringList = {"Bachiri","Taoufiq","Abderrahman"};

Создайте поток из данного массива:

Stream<String> stringStream = Arrays.stream(stringList);

Теперь мы можем выполнить некоторые операции с этим потоком. Например:

Stream<String> myNewStream = stringStream.map(s -> s.toUpperCase());

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

1-классический метод (функциональный интерфейс)

IntFunction<String[]> intFunction = new IntFunction<String[]>() {
    @Override
    public String[] apply(int value) {
        return new String[value];
    }
};


String[] myNewArray = myNewStream.toArray(intFunction);

2-лямбда-выражение

 String[] myNewArray2 = myNewStream.toArray(value -> new String[value]);

3- Ссылка на метод

String[] myNewArray3 = myNewStream.toArray(String[]::new);

Ссылка на метод Объяснение:

Это еще один способ написания лямбда-выражения, которое строго эквивалентно другому.

Бачири Тауфик Абдеррахман
источник
7

Преобразовать текст в строковый массив, где каждое значение разделяется запятой, и обрезать каждое поле, например:

String[] stringArray = Arrays.stream(line.split(",")).map(String::trim).toArray(String[]::new);
Данаил Цветанов
источник
5

Вы можете создать собственный коллектор, который преобразует поток в массив.

public static <T> Collector<T, ?, T[]> toArray( IntFunction<T[]> converter )
{
    return Collectors.collectingAndThen( 
                  Collectors.toList(), 
                  list ->list.toArray( converter.apply( list.size() ) ) );
}

и быстрое использование

List<String> input = Arrays.asList( ..... );

String[] result = input.stream().
         .collect( CustomCollectors.**toArray**( String[]::new ) );
Томас Плиакас
источник
5
Почему вы используете это вместо Stream.toArray (IntFunction) ?
Дидье Л
Мне нужен был коллектор, чтобы перейти к 2-аргументу, Collectors.groupingByчтобы я мог сопоставить некоторый атрибут с массивами объектов по значению атрибута. Этот ответ дает мне именно это. Также @DidierL.
Оле В.В.
3

Использование toArray(IntFunction<A[]> generator)метода действительно является очень элегантным и безопасным способом преобразования (или, точнее, сбора) потока в массив того же типа, что и поток.

Однако, если тип возвращаемого массива не важен, простое использование toArray()метода и проще, и короче. Например:

    Stream<Object> args = Stream.of(BigDecimal.ONE, "Two", 3);
    System.out.printf("%s, %s, %s!", args.toArray());
Кунда
источник
0
Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5, 6);

int[] arr=   stream.mapToInt(x->x.intValue()).toArray();
Радж Н
источник
0
import java.util.List;
import java.util.stream.Stream;

class Main {

    public static void main(String[] args) {
        // Create a stream of strings from list of strings
        Stream<String> myStreamOfStrings = List.of("lala", "foo", "bar").stream();

        // Convert stream to array by using toArray method
        String[] myArrayOfStrings = myStreamOfStrings.toArray(String[]::new);

        // Print results
        for (String string : myArrayOfStrings) {
            System.out.println(string);
        }
    }
}

Попробуйте это онлайн: https://repl.it/@SmaMa/Stream-to-array

Сма Ма
источник
В чем разница между вашим ответом и принятым ответом?
Лонг Нгуен
@LongNguyen Это полный пример, включающий сценарий онлайн-воспроизведения, а не только фрагмент кода.
Сма Ма
-1
     Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5, 6);

     Integer[] integers = stream.toArray(it->new Integer[it]);
Сагар Мал Шанхала
источник
-2

Вы можете сделать это несколькими способами. Все способы технически одинаковы, но использование Lambda упростит часть кода. Допустим, мы сначала инициализируем List с помощью String, назовем его person.

List<String> persons = new ArrayList<String>(){{add("a"); add("b"); add("c");}};
Stream<String> stream = persons.stream();

Теперь вы можете использовать любой из следующих способов.

  1. Использование Lambda Expresiion для создания нового StringArray с определенным размером.

    String [] stringArray = stream.toArray (size-> new String [size]);

  2. Используя ссылку на метод напрямую.

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

раджа эмани
источник