2015-06-06 19 views
15

Desidero implementare uno Stream<T>.Come implementare un flusso Java?

Non voglio usare solo implements Stream<T>, perché dovrei implementare un sacco di metodi.

Questo può essere evitato?

Per essere più concreto, come posso streaming t1, t2 e t3 ad esempio:

class Foo<T> { 
    T t1, t2, t3; 

    Foo(T t1, T t2, T t3) { 
     this.t1 = t1; 
     this.t2 = t2; 
     this.t3 = t3; 
    } 
} 
+8

'Stream.of (t1 , t2, t3) '. –

+3

['Stream.builder'] (https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html#builder--) – fabian

risposta

24

implementazione standard del JDK di Stream è la classe interna java.util.stream.ReferencePipeline, non è possibile creare un'istanza direttamente.

Invece è possibile utilizzare java.util.stream.Stream.builder(), java.util.stream.StreamSupport.stream(Spliterator<T>, boolean) e vari 1, 2 altri metodi factory statici per creare un'istanza della implementazione di default.

L'uso di uno spliterator è probabilmente l'approccio più potente in quanto consente di fornire oggetti pigramente consentendo al tempo stesso una parallelizzazione efficiente se la sorgente può essere suddivisa in più blocchi.

Inoltre, è possibile convertire nuovamente i flussi in spliterator, racchiuderli in uno splitterator personalizzato e quindi convertirli nuovamente in uno stream se è necessario implementare le proprie operazioni intermedie dello stato - ad es. a causa di carenze nelle API standard - dalla maggior parte delle operazioni intermedie disponibili are not allowed to be stateful.
Vedere this SO answer per un esempio.

In linea di principio è possibile scrivere la propria implementazione dell'interfaccia del flusso, ma sarebbe piuttosto noioso.

8

Di solito non è necessario scrivere la propria classe di streaming. Invece puoi creare lo stream con metodi esistenti. Per esempio, ecco come creare un flusso di valore 1, 100:

AtomicInteger n = new AtomicInteger(0); 
    Stream<Integer> stream = Stream.generate(() -> n.incrementAndGet()).limit(100); 

così qui abbiamo creato un flusso infinito di numeri interi: 1, 2, 3, .... poi abbiamo usato il limit(100) quel flusso infinito per ottenere un flusso di 100 elementi.

Per chiarezza, se si desidera un flusso di numeri interi (a intervalli fissi), è necessario utilizzare IntStream.range(). Questo è solo un esempio per mostrare come i flussi possono essere definiti utilizzando Stream.generate() che offre maggiore flessibilità in quanto consente di utilizzare la logica arbitraria per determinare gli elementi del vapore.

+2

' IntStream.range (0,100) ' sarebbe più efficiente in questo caso. – the8472

+0

Questo può essere abbreviato in 'Stream.generate (n :: incrementAndGet) .limit (100)' –

+0

Usa 'n :: getAndIncrement' se vuoi che lo streaming inizi a 0. –

3

Altri hanno risposto a come fornire un'implementazione generica Stream. Per quanto riguarda il tuo specifica requisito, basta fare questo:

class Foo<T> { 

    T t1, t2, t3; 

    Foo(T t1, T t2, T t3) { 
     this.t1 = t1; 
     this.t2 = t2; 
     this.t3 = t3; 
    } 

    Stream<T> stream() { 
     return Stream.of(t1, t2, t3); 
    } 
} 
6

Se hai intenzione di fare il proprio stream perché si vuole personalizzato close() logica, la soluzione più semplice è quello di creare un flusso da un Iterator, e chiamare onClose(Runnable) .Per esempio, per lo streaming da un lettore tramite Jackson:

MappingIterator<?> values = objectMapper.reader(type).readValues(reader); 
return StreamSupport 
     .stream(Spliterators.spliteratorUnknownSize(values, Spliterator.ORDERED), false) 
     .onClose(() -> { 
      try { 
       reader.close(); 
      } catch (IOException e) { 
       throw new RuntimeException(e); 
      } 
     }); 
1

Per ragioni di completezza, in quanto non ho trovato questo direttamente tra le risposte qui su SO: Se si vuole trasformare un Iterator esistente in un flusso (ad esempio, perché si desidera generare gli elementi in successione), utilizzare questo:

StreamSupport.stream(
    Spliterators.spliterator(myIterator, /* initial size*/ 0L, Spliterator.NONNULL), 
    /* not parallel */ false); 

ho trovato questo un po 'difficile da trovare, come è necessario sapere StreamSupport, Spliterators e Spliterator

Problemi correlati