Як перетворити потік Java 8 в масив?


775

Який найпростіший / найкоротший спосіб перетворити Java 8 Streamв масив?


2
Я б запропонував скасувати відкат, оскільки питання було більш повним і показало, що ви щось спробували.
skiwi

2
@skiwi Дякую! але я думав, що спроб коду насправді не додає більше інформації до питання, і ніхто ще не кричав "покажіть нам вашу спробу" поки =)

17
@skiwi: Хоча я зазвичай кричу на питання "робити домашнє завдання", а не "мені", саме це питання мені здається зрозумілішим без будь-якого додаткового безладу. Давайте тримати його в порядку.
Honza Zidek

Ви можете знайти багато відповідей та рекомендацій в офіційних документах пакету: docs.oracle.com/javase/8/docs/api/java/util/stream/…
Крістоф Руссі

Відповіді:


1168

Найпростіший метод - використовувати 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

8
і ось пояснення , чому і як масив посилання конструктора фактично робота: stackoverflow.com/questions/29447561 / ...
jarek.jpa

"Zenexer правильний, рішення повинно бути: stream.toArray (String [] :: new);" ... Ну добре, але варто розуміти, що посилання на метод логічно та функціонально рівнозначне, toArray(sz -> new String[sz])тому я не впевнений, що дійсно можна сказати, яке рішення повинно бути чи повинно бути.
scottb

3
@scottb sz -> new String[sz]робить нову функцію, де, як посилання конструктора, немає. Думаю, залежить, наскільки ви цінуєте збір сміття.
РОБОТИ

3
@WORMSS Це не так. Він (статично!) Створює новий private метод , який не може викликати пошкодження, і для обох версій потрібно створити новий об'єкт. Посилання створює об'єкт, який вказує безпосередньо на цільовий метод; лямбда створює об’єкт, який вказує на створений private. Посилання на конструктор все-таки має краще працювати через відсутність опосередкованості та простішу оптимізацію ВМ, але збивання не має нічого спільного.
HTNW

2
@HTNW ви маєте рацію, вибачте. Це було моєю спробою налагодження, що спричиняло збій, який спричиняв збій, коли я вперше спробував це зробити, тому в мене це застрягло в голові, що це було так. (Ненавиджу, коли це трапляється).
РОБОТИ

41

Якщо ви хочете отримати масив ints зі значеннями від 1 до 10 від Stream, у вашому розпорядженні є IntStream.

Тут ми створюємо Stream методом Stream.of і перетворюємо Stream в IntStream за допомогою mapToInt. Тоді ми можемо викликати метод IntArray 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();

Тут те саме, без Stream, використовуючи лише IntStream

int[]array2 =  IntStream.rangeClosed(1, 10).toArray();

15

Ви можете перетворити потік 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);

Посилання на метод Пояснення:

Це ще один спосіб написання лямбдаського виразу, який суворо еквівалентний іншому.


6

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

String[] stringArray = Arrays.stream(line.split(",")).map(String::trim).toArray(String[]::new);

4

Ви можете створити спеціальний колектор, який перетворить потік у масив.

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)методу - це дійсно дуже елегантний і безпечний спосіб перетворення (або правильніше зібрати) потоку в масив того ж типу Stream.

Однак якщо тип повернутого масиву не важливий, просто використовувати 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 Це повний приклад, включаючи сценарій онлайн-повторення, а не лише фрагмент.
Sma Ma


-2

Це можна зробити кількома способами. Всі способи технічно однакові, але використання Lambda спростить частину коду. Скажімо, ми спочатку ініціалізуємо список зі String, називаємо його особами.

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

Тепер ви можете скористатися одним із наступних способів.

  1. Використання Lambda Expressionion для створення нового StringArray з визначеним розміром.

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

  2. Використання посилання безпосередньо на метод.

    String [] stringArray = stream.toArray (String [] :: новий);

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.