2014-01-19 23 views
18

Ich bin vom java 8 API auf dem Strom Abstraktion zu lesen, aber Ich verstehe nicht, diesen Satz sehr gut:Strom und lazy evaluation

Zwischenoperationen geben einen neuen Stream. Sie sind immer faul; Ausführen einer Zwischenoperation wie filter() nicht tatsächlich führen Sie eine Filterung, aber stattdessen erstellt einen neuen Stream, der, wenn durchlaufen, enthält die Elemente des ersten Datenstroms, die das gegebenen Prädikat entsprechen. Das Traversieren der Pipeline-Quelle beginnt erst, wenn der Terminal-Betrieb der Pipeline ausgeführt wird, und zwar .

Wenn eine Filteroperation einen neuen Stream erstellt enthält dieser Stream gefiltertes Element? Es scheint zu verstehen, dass der Stream Elemente nur enthält, wenn es durchlaufen wird, d. H. Mit einer Terminal-Operation. Aber, was enthält den gefilterten Stream? Ich bin verwirrt!!!

+0

@Lukas, wir haben bereits [tag: java-stream] für die Java 8 Stream API. Das von Ihnen erstellte Tag ist sehr ... generisch. – Charles

+9

Aber sein offizieller Name ist "Streams API", nicht "Java-Stream". Java Stream kann alles bedeuten. Einschließlich InputStream/OutputStream und dergleichen. Wie auch immer, ich denke, das sollte man zum Meta ... –

Antwort

27

Dies bedeutet, dass der Filter nur während des Terminalbetriebs angewendet wird. Denken Sie an etwas wie folgt aus:

public Stream filter(Predicate p) { 
    this.filter = p; // just store it, don't apply it yet 
    return this; // in reality: return a new stream 
} 
public List collect() { 
    for (Object o : stream) { 
     if (filter.test(o)) list.add(o); 
    } 
    return list; 
} 

(Das bedeutet nicht kompilieren und ist eine Vereinfachung der Realität aber das Prinzip ist es)

3

Streams faul sind, weil Zwischenoperationen nicht ausgewertet werden, es sei denn, Terminalbetrieb aufgerufen wird.

Jede Zwischenoperation erstellt einen neuen Stream, speichert die bereitgestellte Operation/Funktion und gibt den neuen Stream zurück.

Die Pipeline akkumuliert diese neu erstellten Streams.

Der Zeitpunkt, zu dem der Terminalbetrieb aufgerufen wird, beginnt mit dem Traversieren von Streams und die zugehörige Funktion wird nacheinander ausgeführt.

Parallele Ströme bewerten Ströme nicht nacheinander (am Endpunkt). Die Operationen werden eher gleichzeitig ausgeführt, abhängig von den verfügbaren Kernen.

1

Es scheint mir, dass Zwischen Betrieb nicht gerade faul:

List<String> l3 = new ArrayList<String>(); 
     l3.add("first"); 
     l3.add("second"); 
     l3.add("third"); 
     l3.add("fouth"); 
     l3.add("fith"); 
     l3.add("sixth"); 

     List<String> test3 = new ArrayList<String>(); 
     try { 
      l3.stream().filter(s -> { l3.clear(); test3.add(s); return true;}).forEach(System.out::println); 
     } catch (Exception ex) { 
      ex.printStackTrace(); 
      System.out.println("!!! "); 
      System.out.println(test3.stream().reduce((s1, s2) -> s1 += " ;" + s2).get()); 
     } 

Otput:

first 
    null 
    null 
    null 
    null 
    null 
    java.util.ConcurrentModificationException 
     at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1380) 
     at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481) 
     at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471) 
     at java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:151) 
     at java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:174) 
     at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) 
     at java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:418) 
     at test.TestParallel.main(TestParallel.java:69) 
    !!! 

    first ;null ;null ;null ;null ;null 

wie die Anzahl der Iteration setzt auf Strom Schaffung Sieht aus, aber einen neuen Stream Element faul Geting.

+0

Könnten Sie bitte Ihren Code formatieren, indem Sie ihn markieren und Strg + K drücken – WhatsThePoint