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


459

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

+2

Я предлагаю вам вернуться к откату, как вопрос был более полным и показал бы вы пытались что-то. 15 апр. 142014-04-15 09:13:21

  0

@skiwi Спасибо! но я думал, что попытка кода на самом деле не добавляет больше информации на вопрос, и никто не кричал «покажи нам твою попытку» еще =) 15 апр. 142014-04-15 09:20:32

+12

@skiwi: Хотя я обычно кричу на домашнюю работу - вместо меня вопросов, этот конкретный вопрос кажется мне более ясным без какого-либо дополнительного беспорядка. Давайте держать его в порядке. 16 апр. 142014-04-16 11:21:24

692

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

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

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

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

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

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

Пример кода:

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

Печать:

a 
b 
c 
+176

'String [] :: new' - хороший трюк; по-моему, более прямолинейно, чем выражение лямбда. 18 дек. 142014-12-18 07:55:54

+11

Zenexer прав, решение должно быть: 'stream.toArray (String [] :: new);' 01 окт. 152015-10-01 13:01:08

+4

и вот объяснение, почему и как работает ссылка конструктора массива: http://stackoverflow.com/ вопросы/29447561/how-do-java-8-array-constructor-references-work 12 сен. 162016-09-12 18:16:38

  0

* "Zenexer прав, решение должно быть: stream.toArray (String [] :: new);" * ... Хорошо нормально , но следует понимать, что ссылка на метод логически и функционально эквивалентна 'toArray (sz -> new String [sz])', поэтому я не уверен, что можно действительно сказать, что должно или должно быть решение. 20 апр. 172017-04-20 14:16:02

  0

Ссылка на конструктор массива более кратка. Документация для метода 'toArray()' цитирует свою сводку и включает ее использование в единственном примере. Когда он был прикреплен в конце ответа, я пропустил его в первом чтении. Переместил его вверх, над деталями, чтобы никто больше не пропустил его. 01 май. 172017-05-01 19:44:05

+2

@scottb 'sz -> new String [sz]' создает новую функцию, где в качестве ссылки на конструктор нет. Это зависит от того, насколько вы оцениваете сбор мусора. 18 авг. 172017-08-18 09:19:42

+1

@WORMSS Это не так. Он (статический!) Создает новый метод 'private' * *, который не может вызывать отток, а * обе версии должны создавать новый объект. Ссылка создает объект, который указывает непосредственно на целевой метод; lambda создает объект, который указывает на сгенерированный «частный». Ссылка на конструктор должна по-прежнему работать лучше из-за отсутствия косвенности и упрощения оптимизации виртуальной машины, но вспенивание не имеет к этому никакого отношения. 29 окт. 172017-10-29 23:54:01

  0

@HTNW вы правы, извинитесь. Это была моя попытка отладки, которая вызывала отторжение, которое вызывало отброс в первый раз, когда я пытался это сделать, поэтому у меня застряло в голове, что так оно и было. (Ненавижу это, когда это произойдет). 30 окт. 172017-10-30 08:38:59


17

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

Здесь мы создаем Stream с методом Stream.of и преобразуем Stream в IntStream с помощью mapToInt. Затем мы можем вызвать метод IntArtream toArray.

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(); 

2

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

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)); 

0
 Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5, 6); 

    Integer[] integers = stream.toArray(it->new Integer[it]); 

0

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

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

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

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

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

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

теперь мы можем выполнять некоторые операции на этом потоке Ex:

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 -Lambda выражение

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

3- Метод опорного

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

Метод Ссылка Пояснение:

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


2

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

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

Stream<Object> args = Stream.of(BigDecimal.ONE, "Two", 3); 
    System.out.printf("%s, %s, %s!", args.toArray());