2015-06-06 20 views
15

Ich möchte eine Stream<T> implementieren.Wie implementiert man einen Java-Stream?

Ich möchte nicht nur implements Stream<T> verwenden, weil ich eine Tonne Methoden implementieren müsste.

Kann dies vermieden werden?

Um konkreter zu sein, wie ich t1, t2 und t3 zum Beispiel streamen:

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

Antwort

24

Die Standardimplementierung von Stream JDK ist die interne Klasse java.util.stream.ReferencePipeline, können Sie es nicht direkt instanziiert werden können.

Stattdessen können Sie java.util.stream.Stream.builder(), java.util.stream.StreamSupport.stream(Spliterator<T>, boolean) und verschiedenen 1, 2 andere statische Factory-Methoden verwenden, um eine Instanz der Standardimplementierung zu erstellen.

Die Verwendung eines Spliterators ist wahrscheinlich der leistungsstärkste Ansatz, da Sie Objekte träge bereitstellen und gleichzeitig eine effiziente Parallelisierung ermöglichen können, wenn Ihre Quelle in mehrere Blöcke unterteilt werden kann.

Zusätzlich können Sie Streams auch in Spliteratoren umwandeln, sie in einen benutzerdefinierten Spliterator umwandeln und sie dann wieder in einen Stream konvertieren, wenn Sie eigene stateful intermediate operations - z. aufgrund von Unzulänglichkeiten in den Standard-APIs - seit den meisten verfügbaren Zwischenoperationen are not allowed to be stateful.
Siehe this SO answer für ein Beispiel.

Im Prinzip könnten Sie Ihre eigene Implementierung der Stream-Schnittstelle schreiben, aber das wäre ziemlich mühsam.

8

Sie müssen normalerweise keine eigene Stream-Klasse schreiben. Stattdessen können Sie einen Stream nach vorhandenen Methoden erstellen. Zum Beispiel, hier ist wie ein Strom von dem Wert zu schaffen 1, 100:

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

so hier wir einen unendlichen Strom von ganzen Zahlen erstellt: 1, 2, 3, .... dann haben wir limit(100) auf dieser unendliche Strom, um einen Strom von 100 Elementen zurückzubekommen.

Aus Gründen der Übersichtlichkeit sollten Sie IntStream.range() verwenden, wenn Sie einen Strom von ganzen Zahlen (in festen Intervallen) möchten. Dies ist nur ein Beispiel, um zu zeigen, wie Streams mit Stream.generate() definiert werden können, was Ihnen mehr Flexibilität gibt, da Sie beliebige Logik zur Bestimmung von Steam-Elementen verwenden können.

+2

' IntStream.range (0,100) ' wäre in diesem Fall effizienter. – the8472

+0

Dies kann abgekürzt werden in 'Stream.generate (n :: incrementAndGet) .limit (100)' –

+0

Verwenden Sie 'n :: getAndIncrement ', wenn der Stream bei 0 beginnen soll. –

3

Andere haben geantwortet, wie man eine allgemeine Stream Implementierung zur Verfügung stellt. In Bezug auf Ihre spezifische Anforderung, dies nur tun:

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

Wenn Sie wollen Ihren eigenen Strom machen, weil Sie benutzerdefinierte close() Logik wollen, einen Strom von einem Iterator, die einfachste Lösung onClose(Runnable) zu erstellen und rufen ist .Zum Beispiel von einem Reader über Jackson streamen:

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

Aus Gründen der Vollständigkeit, da ich das nicht direkt unter den Antworten hier auf SO gefunden: Wenn Sie eine vorhandene Iterator in einen Strom umwandeln wollen (zB weil Sie Elemente nacheinander erzeugen), verwenden Sie diese:

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

fand ich das ein bisschen schwer zu finden, wie Sie wissen müssen StreamSupport, Spliterators und Spliterator

Verwandte Themen