Jak mogę utworzyć strumień z tablicy?

133

Obecnie zawsze, gdy muszę utworzyć strumień z tablicy, robię to

String[] array = {"x1", "x2"};
Arrays.asList(array).stream();

Czy istnieje bezpośredni sposób tworzenia strumienia z tablicy?

adam.kubi
źródło

Odpowiedzi:

201

Możesz użyć Arrays.stream np

Arrays.stream(array);

Możesz także użyć, Stream.ofjak wspomniał @fge, który wygląda jak

public static<T> Stream<T> of(T... values) {
    return Arrays.stream(values);
}

Ale uwaga Stream.of(intArray)zwróci, Stream<int[]>podczas gdy Arrays.stream(intArr)zwróci pod IntStreamwarunkiem, że przekażesz tablicę typu int[]. Zatem w skrócie dla typów prymitywnych można zaobserwować różnicę między 2 metodami np

int[] arr = {1, 2};
Stream<int[]> arr1 = Stream.of(arr);

IntStream stream2 = Arrays.stream(arr); 

Po przekazaniu tablicy pierwotnej do Arrays.streamwywoływany jest następujący kod

public static IntStream stream(int[] array) {
    return stream(array, 0, array.length);
}

a po przekazaniu tablicy pierwotnej do Stream.ofnastępującego kodu jest wywoływana

 public static<T> Stream<T> of(T t) {
     return StreamSupport.stream(new Streams.StreamBuilderImpl<>(t), false);
 }

Dlatego otrzymujesz różne wyniki.

Zaktualizowano : Jak wspomniał komentarz Stuarta Marksa Przeciążenie podzakresu Arrays.streamjest lepsze niż używanie, Stream.of(array).skip(n).limit(m)ponieważ pierwszy daje strumień SIZED, podczas gdy drugi nie. Powodem jest to, że limit(m)nie wie, czy rozmiar jest m, czy mniejszy niż m, podczas Arrays.streamgdy sprawdza zakres i zna dokładny rozmiar strumienia.Możesz odczytać kod źródłowy implementacji strumienia zwracany Arrays.stream(array,start,end) tutaj , podczas gdy dla implementacji strumienia zwracanego przez Stream.of(array).skip().limit()jest w ramach tej metody .

sol4me
źródło
9
Ta odpowiedź jest lepsza, ponieważ Arrays.streamzawiera wszystkie przeciążone przypadki dla tablic pierwotnych. To znaczy, Stream.of(new int[]{1,2,3})że da ci, Stream<int[]>podczas gdy Arrays.streamzwróci ci to, IntStreamco prawdopodobnie jest tym, czego chcesz. Więc +1
user2336315
3
@Dima Myślę, że to kwestia gustu. Chodzi mi o to, że lepsze w pewnym sensie Stream.ofmoże dać ci kilka niespodzianek (na przykład, gdy dzwonisz Arrays.asListz prymitywną tablicą i ludzie oczekują List<Integer>odwrotu) :-)
user2336315
3
Arrays.streamobsługuje przesyłanie strumieniowe zakresu tablicy, co IntStream.ofnie. W przeciwieństwie do tego, Stream.ofjest to lepszy wybór, jeśli chcesz mieć Stream<int[]>rozmiar 1
Holger
4
@Dima Przeciążenie podzakresu Arrays.streamjest lepsze niż użycie, Stream.of(array).skip(n).limit(m)ponieważ pierwszy daje strumień SIZED, a drugi nie. Powodem jest to, że limit(m)nie wie, czy rozmiar jest, mczy mniejszy niż m, podczas Arrays.streamgdy sprawdza zakres i zna dokładny rozmiar strumienia.
Stuart Marks
6
Dla czytelników, którzy są zainteresowani zakończeniem tego małego dramatu, Arrays.stream(array,start,end)zwraca a, Streamktórego implementacja jest tutaj , natomiast Stream.of(array).skip().limit()zwraca a, Streamktórej implementacja znajduje się w tej metodzie .
Stuart Marks
43

Alternatywa dla rozwiązania @ sol4me:

Stream.of(theArray)

Różnica między this i Arrays.stream(): ma znaczenie, jeśli twoja tablica jest typu pierwotnego. Na przykład, jeśli:

Arrays.stream(someArray)

gdzie someArrayjest a long[], zwróci LongStream. Stream.of()z drugiej strony zwróci a Stream<long[]>z jednym elementem.

fge
źródło
1
@Dima na pewno, ale też Arrays.stream()do tego działa
fge
2
Cóż, jeśli chodzi o strumienie, wygoda! Nie musisz dzwonić, *Stream.of()gdy masz do Arrays.stream()czynienia z prymitywnymi tablicami. A jeśli chodzi o tablice, które nie są rzeczywistymi obiektami, cóż, to jest Java, tak było od wersji 1.0, więc zajmij się tym; rozmyślanie nad tym nic nie pomaga
fge
2
@Dima i tak jest Twoje; uważasz, że Arrays.stream()nie jest to wygodne, uważam to za wygodne. Wystarczająco powiedziane.
fge
2
@Dima tak, uważam, że twój argument *Stream.of()jest wygodniejszy, gdy jest fałszywy; bo to kwestia preferencji . Preferuję Arrays.stream()takie przypadki, co sprawia, że ​​z reguły Stream.of()jest to błędne, co jest wygodniejsze (algebra Peano).
fge
3
@Dima: to kwestia preferencji. Różnice są tak niewiarygodnie małe, że nie ma to żadnego znaczenia. A dokładniej: różnica kilku postaci to nic . Dodatkowy import do pakietu wewnątrz standardowych bibliotek to nic . I tak naprawdę, ręczne tworzenie tablicy zamiast przeciążenia varargs to nic .
Jeroen Vannevel
14
Stream.of("foo", "bar", "baz")

Lub, jeśli masz już tablicę, możesz to zrobić

Stream.of(array) 

W przypadku typów pierwotnych użyj IntStream.oflub LongStream.ofitp.

Dima
źródło
Nie rozumiem, że skoro int[]można przekazać metodę akceptującą varargs, dlaczego nie Stream.of(intArray)utworzy Stream<Integer>zamiast Stream<int[]>? Czy jest też jakieś techniczne uzasadnienie, dlaczego istnieją wyspecjalizowane klasy Stream dla prymitywów?
asgs
1
Prymitywy Java to dziwne bestie. int[]nie jest jak inne tablice. To nie jest podklasa klasy Object[], ale jest to podklasa klasy Object. Tak więc, kiedy przekazujesz go do Stream.of, jest przyjmowany jako Objectparametr, i otrzymujesz strumień int[]. Jest to jeden z powodów, dla których warto mieć wyspecjalizowane klasy dla prymitywów - gdybyś nie tworzył strumieni z prymitywnych tablic, byłoby to dość bolesne. Innym powodem jest to, że specjalistyczne zajęcia są bardziej efektywne, ponieważ nie trzeba ponosić Objectnarzut z boksu (konwersja intdo Integer, aby wyglądać jak zwykłe obiekty).
Dima,
Ach, ponieważ int[]jest Object, to pasowałoby do przeciążonej metody of(T t)i dlatego zwraca Stream<int[]>. Czyli teoretycznie, gdyby ta metoda nie była dostępna, otrzymalibyśmy Stream<Integer>w zamian? a może skutkuje to błędem kompilacji, ponieważ nie może znaleźć pasującej metody? tj. int[]nie można traktować jakoT...
asgs
1
Nie, nadal nie osiągnęlibyśmy Stream<Integer>tego, ponieważ Stream.of(t ... T) nadal pasowalibyśmy w ten sam sposób.
Dima
0

Można to zrobić również metodą niskopoziomową z opcją równoległą:

Aktualizacja: użyj pełnej tablicy.length (nie długość - 1).

/** 
 * Creates a new sequential or parallel {@code Stream} from a
 * {@code Spliterator}.
 *
 * <p>The spliterator is only traversed, split, or queried for estimated
 * size after the terminal operation of the stream pipeline commences.
 *
 * @param <T> the type of stream elements
 * @param spliterator a {@code Spliterator} describing the stream elements
 * @param parallel if {@code true} then the returned stream is a parallel
 *        stream; if {@code false} the returned stream is a sequential
 *        stream.
 * @return a new sequential or parallel {@code Stream}
 *
 * <T> Stream<T> stream(Spliterator<T> spliterator, boolean parallel)
 */

StreamSupport.stream(Arrays.spliterator(array, 0, array.length), true)
merqlove
źródło
0

Możesz użyć Arrays.stream:

Arrays.stream (tablica); 

Zapewnia to typ zwracany pary na podstawie typu array wejście, jeśli jej String []następnie powrócić Stream<String>, jeśli int []następnie powracaIntStream

Jeśli znasz już tablicę typów wejściowych, dobrze jest użyć konkretnej tablicy, takiej jak typ wejściowy int[]

 IntStream.of (tablica); 

To zwraca Intstream.

W pierwszym przykładzie Java używa metody overloadingdo znalezienia określonej metody na podstawie typów danych wejściowych, podczas gdy w drugim znasz już typ danych wejściowych i wywołujesz określoną metodę.

vipul patel
źródło
0

rzadko spotykane, ale to jest najprostsza droga

Stream.Builder<String> builder = Stream.builder();
for( int i = 0; i < array.length; i++ )
  builder.add( array[i] );
Stream<String> stream = builder.build();
Kaplan
źródło