Jak przekonwertować strumień Java 8 na macierz?

775

Jaki jest najłatwiejszy / najkrótszy sposób na konwersję Java 8 Streamna tablicę?

MC Emperor
źródło
2
Sugeruję, abyś cofnął wycofanie, ponieważ pytanie było bardziej kompletne i pokazało, że próbowałeś czegoś.
skiwi
2
@skiwi Thanks! ale myślałem, że próba wykonania kodu nie dodaje więcej informacji do pytania i nikt jeszcze nie krzyknął: „pokaż nam swoją próbę” =)
17
@skiwi: Chociaż zwykle krzyczę na pytania „odrabiam pracę domową” zamiast „ja”, to pytanie wydaje mi się bardziej zrozumiałe bez dodatkowego bałaganu. Zachowajmy porządek.
Honza Zidek
Wiele odpowiedzi i wskazówek można znaleźć w oficjalnych dokumentach pakietu: docs.oracle.com/javase/8/docs/api/java/util/stream/…
Christophe Roussy

Odpowiedzi:

1168

Najłatwiejszą metodą jest użycie toArray(IntFunction<A[]> generator)metody z referencją do konstruktora tablic. Jest to sugerowane w dokumentacji interfejsu API dla tej metody .

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

To, co robi, to znalezienie metody, która przyjmuje liczbę całkowitą (rozmiar) jako argument i zwraca a String[], czyli dokładnie to, co robi (jedno z przeciążeń) new String[].

Możesz także napisać własny IntFunction:

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

Celem tego IntFunction<A[]> generatorjest przekonwertowanie liczby całkowitej, rozmiaru tablicy, na nową tablicę.

Przykładowy kod:

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

Wydruki:

a
b
c
skiwi
źródło
8
a oto wyjaśnienie, dlaczego i jak faktycznie działa odwołanie do konstruktora Array: stackoverflow.com/questions/29447561/…
jarek.jpa
„Zenexer ma rację, rozwiązaniem powinno być: stream.toArray (String [] :: new);” ... No dobrze, ale należy zrozumieć, że odwołanie do metody jest logicznie i funkcjonalnie równoważne, toArray(sz -> new String[sz])więc nie jestem pewien, czy naprawdę można powiedzieć, jakie rozwiązanie powinno lub musi być.
scottb
3
@scottb sz -> new String[sz]wprowadza nową funkcję, w której nie ma odwołania do konstruktora. To zależy od tego, jak bardzo cenisz śmieciowanie śmieci.
WORMSS,
3
@ WORMSS Nie. To (statycznie!) Tworzy nową private metodę , która nie może powodować rezygnacji, i obie wersje muszą utworzyć nowy obiekt. Odwołanie tworzy obiekt, który wskazuje bezpośrednio na metodę docelową; lambda tworzy obiekt wskazujący na wygenerowany private. Odwołanie do konstruktora powinno nadal działać lepiej ze względu na brak pośrednictwa i łatwiejszą optymalizację maszyn wirtualnych, ale ubijanie nie ma z tym nic wspólnego.
HTNW,
2
@HTNW masz rację, przepraszam. To była moja próba debugowania, która spowodowała odejście, które spowodowało odejście, gdy próbowałem to zrobić po raz pierwszy, więc utknąłem w głowie, że tak było. (Nienawidzę, kiedy to się dzieje).
WORMSS,
41

Jeśli chcesz uzyskać tablicę liczb całkowitych o wartościach od 1 do 10 ze strumienia, masz do dyspozycji IntStream.

Tutaj tworzymy strumień metodą Stream.of i konwertujemy strumień do IntStream za pomocą mapToInt. Następnie możemy wywołać metodę toArray 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();

Oto to samo, bez Strumienia, używając tylko IntStream

int[]array2 =  IntStream.rangeClosed(1, 10).toArray();
Ida Bucić
źródło
15

Możesz przekonwertować strumień Java 8 na tablicę za pomocą tego prostego bloku kodu:

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

Ale wyjaśnijmy więcej, najpierw stwórzmy listę łańcuchów wypełnionych trzema wartościami:

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

Utwórz strumień z podanej tablicy:

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

możemy teraz wykonać niektóre operacje na tym strumieniu. Przykład:

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

i na koniec przekonwertować go na java 8 Array przy użyciu następujących metod:

Metoda 1-klasyczna (interfejs funkcjonalny)

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


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

2-wyrażenie lambda

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

3- Odniesienie do metody

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

Odwołanie do metody Objaśnienie:

Jest to inny sposób pisania wyrażenia lambda, który jest ściśle równoważny z drugim.

Bachiri Taoufiq Abderrahman
źródło
6

Konwertuj tekst na tablicę łańcuchów, gdzie oddzielamy każdą wartość przecinkiem, i przycinaj wszystkie pola, na przykład:

String[] stringArray = Arrays.stream(line.split(",")).map(String::trim).toArray(String[]::new);
Danail Tsvetanov
źródło
4

Możesz utworzyć niestandardowy moduł zbierający, który konwertuje strumień na tablicę.

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

i szybkie użycie

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

String[] result = input.stream().
         .collect( CustomCollectors.**toArray**( String[]::new ) );
Thomas Pliakas
źródło
5
Dlaczego miałbyś używać tego zamiast Stream.toArray (IntFunction) ?
Didier L,
Potrzebowałem kolektora, aby przejść do 2-argumentu, Collectors.groupingByaby móc mapować niektóre atrybuty na tablice obiektów według wartości atrybutu. Ta odpowiedź daje mi dokładnie to. Również @DidierL.
Ole VV
3

Używając toArray(IntFunction<A[]> generator) metody jest w rzeczywistości bardzo eleganckim i bezpiecznym sposobem konwersji (lub, bardziej poprawnie, zbierania) Strumienia na tablicę tego samego typu Strumienia.

Jeśli jednak typ zwracanej tablicy nie jest ważny, po prostu użycie toArray()metody jest zarówno łatwiejsze, jak i krótsze. Na przykład:

    Stream<Object> args = Stream.of(BigDecimal.ONE, "Two", 3);
    System.out.printf("%s, %s, %s!", args.toArray());
Kunda
źródło
0
Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5, 6);

int[] arr=   stream.mapToInt(x->x.intValue()).toArray();
Raj N.
źródło
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);
        }
    }
}

Wypróbuj online: https://repl.it/@SmaMa/Stream-to-array

Sma Ma
źródło
Jaka jest różnica między odpowiedzią a odpowiedzią zaakceptowaną?
Długi Nguyen
@LongNguyen To pełny przykład, w tym scenariusz powtórki online, a nie tylko fragment.
Sma Ma
-1
     Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5, 6);

     Integer[] integers = stream.toArray(it->new Integer[it]);
Sagar Mal Shankhala
źródło
-2

Możesz to zrobić na kilka sposobów: wszystkie są technicznie takie same, ale użycie Lambdy uprościłoby część kodu. Powiedzmy, że najpierw inicjujemy Listę ciągiem, nazywamy ją osobami.

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

Teraz możesz użyć jednego z następujących sposobów.

  1. Użycie Lambda Expresiion do utworzenia nowego StringArray o zdefiniowanym rozmiarze.

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

  2. Bezpośrednie użycie metody

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

raja emani
źródło