2015-04-22 15 views
5

Ich habe auf Java 8 Streams und die Art und Weise, wie Daten aus einer Datenquelle gestreamt werden, gelesen, anstatt die gesamte Sammlung aus Daten extrahieren zu müssen.Java 8 Stream vs Collection Speicher

Dieses Zitat insbesondere ich auf einen Artikel über Ströme in Java lesen 8.

„Keine Speicher Streams haben keine Speicher für Werte;. Sie tragen Werte von einer Quelle (die eine Datenstruktur sein könnte, eine Erzeugungsfunktion, ein I/O-Kanal usw.) durch eine Pipeline von Rechenschritten. " Von der Quelle: http://www.drdobbs.com/jvm/lambdas-and-streams-in-java-8-libraries/240166818?pgno=1

verstehe ich das Konzept der Streaming-Daten in von einer Quelle Stück für Stück. Was ich nicht verstehe ist, wenn Sie aus einer Sammlung streamen, wie ist kein Speicher? Die Sammlung existiert bereits auf dem Heap, Sie streamen nur die Daten aus dieser Sammlung, die Sammlung existiert bereits im "Speicher".

Was ist der Unterschied Memory-Footprint weise, wenn ich nur die Sammlung mit einem Standard für Schleife durchlaufen würde?

Antwort

17

Die Aussage über Streams und Speicher bedeutet, dass ein Stream keinen eigenen Speicher hat. Wenn die Quelle des Streams eine Sammlung ist, verfügt diese Sammlung offensichtlich über Speicher, um die Elemente zu speichern.

ist eines der Beispiele aus diesem Artikel nehmen lassen:

int sum = shapes.stream() 
       .filter(s -> s.getColor() == BLUE) 
       .mapToInt(s -> s.getWeight()) 
       .sum(); 

Angenommen, shapes ein Collection, dass Millionen von Elementen hat. Man könnte sich vorstellen, dass die Operation filter über die Elemente der Quelle iteriert und eine temporäre Sammlung von Ergebnissen erstellt, die möglicherweise auch Millionen von Elementen enthalten. Die Operation mapToInt könnte dann über diese temporäre Sammlung hinweg iterieren und ihre zu summierenden Ergebnisse erzeugen.

So funktioniert das nicht. Es gibt keine temporäre Zwischenabholung. Die Stream-Operationen sind pipelineartig, so dass Elemente, die aus filter hervorgehen, durch mapToInt und danach zu sum geleitet werden, ohne dass sie in einer Sammlung gespeichert und von dieser gelesen werden.

Wenn die Stream-Quelle keine Sammlung war - also Elemente aus einer Netzwerk-Sammlung gelesen wurden -, muss überhaupt kein Speicher vorhanden sein. Eine Pipeline wie die folgende:

int sum = streamShapesFromNetwork() 
       .filter(s -> s.getColor() == BLUE) 
       .mapToInt(s -> s.getWeight()) 
       .sum(); 

könnte Millionen von Elementen verarbeiten, aber es müsste nicht Millionen von Elementen irgendwo speichern.

3

Stellen Sie sich den Strom als eine Düse vor, die mit dem Wassertank verbunden ist, der Ihre Datenstruktur darstellt. Die Düse hat keinen eigenen Speicher. Sicher, das Wasser (Daten), das der Stream liefert, kommt von einer Quelle, die Speicher hat, aber der Stream selbst hat keinen Speicher. Wenn Sie eine weitere Düse (Stream) an Ihren Tank (Datenstruktur) anschließen, benötigen Sie keinen Speicher für eine neue Kopie der Daten.

+0

Danke für die Antwort! Ich verstehe den Daten-Streaming-Teil, aber was ist der Speicher- (Speicher-) Overhead, wenn ich die Sammlung direkt verwenden möchte, anstatt sie zu streamen? Wenn ich die Sammlung direkt verwende, greife ich auf die Sammlung auf dem Heap zu, wenn ich sie streame, streame ich immer noch die Daten aus der Sammlung, die sich auf dem Heap befindet. In beiden Fällen bleibt der Speicher-Footprint in beiden Methoden gleich. Bitte korrigieren Sie mich, wenn ich falsch liege/etwas hier vermisse. – user3587411

+0

@ user3587411: Es gibt im Wesentlichen keinen Unterschied. Ein Weg könnte ein paar mehr Stapelrahmen und temporäre Objekte verwenden, aber das sind nur ein paar Bytes. – user2357112

+0

* "In beiden Fällen bleibt der Speicher-Footprint gleich." * Der Zweck eines Streams besteht nicht darin, Speicher zu sparen. – Radiodef

3

Ein Stream ist nur eine Ansicht der Daten, es hat keinen eigenen Speicher und Sie können die zugrunde liegende Sammlung (vorausgesetzt, es ist ein Stream, der auf einer Sammlung aufgebaut wurde) nicht durch den Stream ändern. Es ist wie ein "Nur-Lese" -Zugriff.

Wenn Sie RDBMS Erfahrung haben - es ist die gleiche Idee von "Ansicht".

0
  1. Sammlung ist eine Datenstruktur. Basierend auf dem Problem entscheiden Sie, welche Sammlung wie ArrayList, LinekedList (Berücksichtigung von Zeit- und Raumkomplexität) verwendet werden soll. Wo Stream ist nur eine Art der Verarbeitung von Werkzeug, das Ihr Leben einfach macht.

  2. Andere Unterschied ist, können Sie Collection als In-Memory-Datenstruktur betrachten, wo Sie Elemente hinzufügen, entfernen können. Wo in Stream können Sie zwei Arten von Betrieb durchführen:

    a. Zwischenbetrieb: Filter, Karte, Sortierung, Begrenzung der Ergebnismenge
    b. Terminaloperation: forEach, sammeln Sie die Ergebnismenge zu einer Sammlung.

    Aber wenn Sie bemerken, mit Stream können Sie keine Elemente hinzufügen oder entfernen.

  3. Stream- ist eine Art Iterator, Sie Sammlung durch den Strom überqueren können. Beachten Sie, dass Sie Strom nur einmal durchlaufen können, lassen Sie mich Ihnen ein Beispiel geben ein besseres Verständnis zu haben:

Example1:

List<String> employeeNameList = Arrays.asList("John","Peter","Sachin"); 
    Stream<String> s = employeeNameList.stream(); 

    // iterate through list 
    s.dorEach(System.out :: println); // this work's perfectly fine 
    s.dorEach(System.out :: println); // you will get IllegalStateException, stating stream already operated upon 

Also, was können Sie entnehmen ist, Sammlung Sie iterieren können so viele mal wie du willst. Aber für den Stream, sobald Sie iterieren, wird es sich nicht mehr erinnern, was es tun soll. Also müssen Sie es erneut anweisen.

Ich hoffe, es ist klar.