2015-02-28 13 views
51

C'è un buon modo per aggiungere un nuovo valore a esistente Stream? Tutto quello che posso immaginare è qualcosa di simile:Aggiunta di un nuovo valore a Stream esistente

public <T> Stream<T> addToStream(Stream<T> stream, T elem) { 
    List<T> result = stream.collect(Collectors.toList()); 
    result.add(elem); 
    return result.stream(); 
} 

Ma io sto cercando qualcosa di più concisa che posso utilizzare in un'espressione lambda, senza verbosità.

Un'altra domanda è apparso quando ho cercato di implementare PECS principio:

public <T> Stream<? super T> addToStream(Stream<? super T> stream, T elem) { 
    List<? super T> result = stream.collect(Collectors.toList()); //error 
    result.add(elem); 
    return result.stream(); 
} 

Sembra come jolly non funziona con Stream.collect e mi chiedo perché. Grazie in anticipo.

+0

Non c'è alcuna garanzia che la 'Lista' restituita da' collect (Collectors.toList()) 'supporti' add', puoi usare 'Collectors.toCollection' invece di scegliere il tipo di lista che ottieni. – Alex

risposta

66

La domanda smentisce un'ipotesi errata: gli stream contengono effettivamente i loro dati. Loro non; i flussi non sono strutture di dati, sono un mezzo per specificare operazioni di massa su una varietà di fonti di dati.

Esistono combinatori per combinare due flussi in uno, come Stream.concat e fabbriche per creare flussi da un insieme di elementi noti (Stream.of) o da collezioni (Collection.stream). Quindi puoi combinarli se vuoi produrre un nuovo stream che è la concatenazione del flusso che hai in mano, insieme a un nuovo stream che descrive i nuovi elementi.

Il problema nell'esempio PECS è che ci sono tre occorrenze di ? super T e si presuppone che descrivano lo stesso tipo, ma non lo fanno. Ogni occorrenza di un jolly corrisponde a un'acquisizione unica, che non è ciò che desideri; è necessario assegnare un nome a tale variabile di tipo, in modo che il compilatore sappia che il tipo di elenco e il tipo del flusso di input sono gli stessi. (Inoltre, non materializzare una collezione, che è costoso e potenzialmente non terminante se lo stream non è finito. Basta usare concat.) Quindi la risposta è: hai appena sbagliato i generici. Ecco un modo per farlo:

public<T> Stream<T> appendToStream(Stream<? extends T> stream, T element) { 
    return Stream.concat(stream, Stream.of(element)); 
} 

Tu stesso confuso con PECS perché stavi pensando di "inserimento" nel flusso, quando in realtà si sta consumando da esso.

+7

Il metodo non deve essere denominato "appendToStream"? Altrimenti penso che i parametri del metodo concat dovrebbero essere cambiati. –

22

Come su

return Stream.concat(stream, Stream.of(elem)); 

Ciò presuppone l'originale Stream è finita. Se non lo è, puoi concatenarli in ordine inverso.

+0

grazie, ma per quanto riguarda la seconda domanda? – Dmytro

Problemi correlati