Come posso creare uno stream da un array?


133

Attualmente, ogni volta che devo creare un flusso da un array, lo faccio

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

Esiste un modo diretto per creare stream da un array?

Risposte:


201

Puoi usare Arrays.stream ad es

Arrays.stream(array);

Puoi anche usare Stream.ofcome indicato da @fge, che sembra

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

Ma la nota Stream.of(intArray)verrà restituita Stream<int[]>mentre Arrays.stream(intArr)verrà restituita IntStreamfornendo una matrice di tipo int[]. Quindi, in breve, per il tipo di primitive è possibile osservare la differenza tra 2 metodi, ad es

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

IntStream stream2 = Arrays.stream(arr); 

Quando si passa alla matrice primitiva Arrays.stream, viene richiamato il seguente codice

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

e quando si passa la matrice primitiva al Stream.ofseguente codice viene richiamato

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

Quindi ottieni risultati diversi.

Aggiornato : come menzionato dal commento di Stuart MarksArrays.stream È preferibile utilizzare Stream.of(array).skip(n).limit(m)il sovraccarico subrange perché il primo risulta in un flusso SIZED mentre il secondo no. Il motivo è che limit(m)non sa se la dimensione è m o inferiore a m, mentre Arrays.streamcontrolla gli intervalli e conosce la dimensione esatta del flusso È possibile leggere il codice sorgente per l'implementazione del flusso restituito Arrays.stream(array,start,end) qui , mentre per l'implementazione del flusso restituito Stream.of(array).skip().limit()è all'interno di questo metodo .


9
Questa risposta è migliore perché Arrays.streamha tutti i casi sovraccaricati di array primitivi. Cioè Stream.of(new int[]{1,2,3})ti darò un Stream<int[]>considerando Arrays.streamche ti restituirà quello IntStreamche probabilmente è quello che vuoi. Quindi +1
user2336315

3
@Dima immagino sia una questione di gusti. Voglio dire, meglio in un certo senso Stream.ofpotrebbe darti delle sorprese (come quando chiami Arrays.asListcon un array primitivo e che la gente si aspetta un List<Integer>ritorno) :-)
user2336315

3
Arrays.streamsupporta lo streaming di un intervallo dell'array, il che IntStream.ofnon lo fa. Al contrario, Stream.ofè la scelta migliore se si desidera una Stream<int[]>taglia 1...
Holger,

4
@Dima Arrays.streamÈ preferibile utilizzare Stream.of(array).skip(n).limit(m)il sovraccarico subrange di perché il primo genera un flusso SIZED mentre il secondo no. Il motivo è che limit(m)non sa se la dimensione è mo meno di m, mentre Arrays.streamcontrolla i range e conosce la dimensione esatta del flusso.
Stuart segna l'

6
Per i lettori interessati a vedere concluso questo piccolo dramma, Arrays.stream(array,start,end)restituisce a la Streamcui implementazione è presente , mentre Stream.of(array).skip().limit()restituisce a la Streamcui implementazione rientra in questo metodo .
Stuart segna il

43

Alternativa alla soluzione di @ sol4me:

Stream.of(theArray)

Della differenza tra questo e Arrays.stream(): fa la differenza se l'array è di tipo primitivo. Ad esempio, se lo fai:

Arrays.stream(someArray)

dove someArrayè a long[], restituirà a LongStream. Stream.of(), d'altra parte, restituirà a Stream<long[]>con un singolo elemento.


1
@Dima certo, ma Arrays.stream()funziona anche per quello
fge

2
Bene, per quanto riguarda i flussi, convenienza! Non è necessario chiamare *Stream.of()quando si ha a che Arrays.stream()fare con array primitivi. E per quanto riguarda le matrici che non sono oggetti reali, beh, questo è Java, questo è il caso dalla 1.0, quindi affrontatelo; rimuginare su questo non aiuta a nulla
fge

2
@Dima e anche il tuo; si considera Arrays.stream()non essere conveniente, mi considero conveniente. È stato detto abbastanza.
fge

2
@Dima sì, trovo il tuo argomento *Stream.of()più conveniente per essere fallace; perché è una questione di preferenze . Preferisco Arrays.stream()per questi casi, il che rende sbagliato come regola generale Stream.of()più conveniente (algebra di Peano).
fge

3
@Dima: è una questione di preferenza. Le differenze sono così incredibilmente minuscole che non importa affatto. Più specificamente: una differenza di alcuni personaggi non è nulla . Un'ulteriore importazione in un pacchetto all'interno delle librerie standard non è nulla . E davvero, creare manualmente un array anziché un sovraccarico varargs non è niente .
Jeroen Vannevel,

14
Stream.of("foo", "bar", "baz")

Oppure, se hai già un array, puoi anche farlo

Stream.of(array) 

Per tipi primitivi usare IntStream.ofo LongStream.ofecc.


Quello che non capisco è, quando un int[]può essere passato a un metodo che accetta varargs, perché non Stream.of(intArray)produrre un Stream<Integer>invece di Stream<int[]>? Inoltre, c'è qualche ragionamento tecnico per cui esistono classi Stream specializzate per le primitive?
chiede il

1
Le primitive Java sono bestie strane. int[]non è come gli altri array. Non è una sottoclasse di Object[], ma è una sottoclasse di Object. Quindi, quando lo passi a Stream.of, viene preso come Objectparametro, e ottieni un flusso di int[]. Questo è uno dei motivi per avere lezioni specializzate per le primitive - se non creassi flussi da array primitivi sarebbe piuttosto doloroso. L'altro motivo è che le classi specializzate sono più efficienti, perché non devono sostenere il Objectsovraccarico del pugilato (convertendolo intin Integerper renderlo simile agli oggetti normali).
Dima,

Ah, poiché int[]è un Object, corrisponderebbe al metodo sovraccarico of(T t)e quindi ritorna Stream<int[]>. Quindi, teoricamente parlando, se questo metodo non fosse disponibile, avremmo ottenuto Stream<Integer>in cambio? o forse provoca un errore di compilazione perché non è stato possibile trovare il metodo di corrispondenza? cioè int[]non può essere trattato comeT...
asgs

1
No, non saremmo ancora Stream<Integer>così, perché Stream.of(t ... T) corrisponderebbero comunque allo stesso modo.
Dima,

0

Puoi farlo anche con un metodo di basso livello che ha un'opzione parallela:

Aggiornamento: usa array.length completo (non lunghezza - 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)

0

Puoi usare Arrays.stream:

Arrays.stream (array); 

Ciò garantisce il tipo di ritorno di vapore in base al tipo di input dell'array se String []poi ritorna Stream<String>, se int []poi ritornaIntStream

Quando conosci già l'array del tipo di input, allora è bene usarne uno specifico come per il tipo di input int[]

 IntStream.of (array); 

Questo restituisce Intstream.

Nel primo esempio, Java utilizza il metodo overloadingper trovare un metodo specifico basato sui tipi di input, mentre come nel secondo si conosce già il tipo di input e il metodo specifico di chiamata.


0

raramente visto, ma questo è il modo più diretto

Stream.Builder<String> builder = Stream.builder();
for( int i = 0; i < array.length; i++ )
  builder.add( array[i] );
Stream<String> stream = builder.build();
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.