2017-10-11 4 views
10

Schließt die die stream implizit, oder muss sie explizit danach geschlossen werden?Schließt der Stream.spliterator() den Stream?

Stream<String> stream = Stream.of("a", "b", "c"); 
Spliterator<T> spliterator = stream.spliterator(); 
// Some low lever operation with the spliterator 
stream.close(); // do we need to close? 

Auf den ersten Blick scheint es, dass die .spliterator() Methode, um die stream schließt, aber ohne stream.close() aufrufen. Zumindest wenn ich es sofort schließe, nachdem die .spliterator() Methode aufgerufen wird, scheint es keine Zuneigung der Spliteratoroperationen zu sein.

Stream<String> stream = Stream.of("a", "b", "c").limit(2); 
Spliterator<T> spliterator = stream.spliterator(); 
stream.close(); 
// Some low lever operation with the spliterator 

Diese Frage kann auf andere stream Methoden erweitert werden, beispielsweise die .findAny().

stream.findAny() // Can I assume that I don't need to close the stream? 
stream.onClose(() -> System.out.println("hi!")).findAny()` 
// when the `onClose()` action will be called? 

Der Grund für diese Frage ist tief Klarheit zu haben, wenn ein stream Bedürfnisse explizit geschlossen werden, und in den Fällen, in denen ich brauche nicht ausdrücklich um es zu schließen, wenn die onClose() definierten Aktionen stattfinden?

+0

Stream-Schnittstelle erweitert die AutoCloseable-Schnittstelle, so dass Gast die OnClose-Aktionen irgendwann aufgerufen werden, wenn der Garbage Collector den Stream disponiert. Es ist jedoch die beste Vorgehensweise, es so schnell wie möglich zu schließen. – Tet

+4

Nein, es gibt keinen Garbage Collector, der das Schließen des Streams steuert - und die Ergebnisse wären katastrophal, wenn der Stream einen solchen Finalizer hätte. Die zugrunde liegende Ressource selbst * kann eine automatische Bereinigung haben, aber das hängt von der Ressource ab. Das bedeutet jedoch nicht, dass ein Close-Handler ausgeführt wird, der für den Stream registriert ist. – Holger

+2

Nur um Details hinzuzufügen, hier ist ein guter Einblick über Streams und [TWR von Stuart] (https://Stackoverflow.com/a/22929990/1746118) – nullpointer

Antwort

8

Terminal-Operationen ausführen nie den Stream schließen. Das Schließen muss manuell erfolgen. Der einzige Ort, an dem das automatische Schließen stattfindet, ist der Vorgang flatMap, bei dem das manuelle Schließen der Subströme, die normalerweise während des Betriebs erzeugt werden, irgendwo zwischen schwierig und unmöglich ist.

Dies gilt auch für die Stream.spliterator() Methode. In Ihren Beispielen macht das keinen Unterschied, da die über Stream.of(…) erstellten Streams nicht geschlossen werden müssen und standardmäßig keine onClose-Operation registriert sind.

Sie müssen die Dokumentation der Factory-Methoden konsultieren, um herauszufinden, wann ein Stream geschlossen werden muss, z. wie mit Files#lines(Path, Charset).

Siehe Does collect operation on Stream close the stream and underlying resources? oder Does Java 8 Stream.iterator() auto-close the stream when it's done?

+0

Danke @Holger, nur für Informationen, wenn eine Terminal-Operation den Stream in einem unbrauchbaren Zustand (z. B. '.findAny()') verlässt, warum schließt die Terminal-Operation den Strom selbst nicht vor der Rückgabe des Wertes? – Tet

+2

@Tet: Es folgt der Grundsatz, dass die Verantwortung des Schließens beim Ersteller der Ressource liegt und die Terminaloperation die Ressource nicht zugeteilt hat. Entsprechend schließt sich ein 'InputStream' nicht selbst, wenn Sie das letzte Byte lesen. – Holger

4

In Bezug auf das Schließen von Stream in Java hat sich nichts geändert. 9. Sie müssen es immer noch manuell tun, wenn die zugrunde liegende Ressource freigegeben werden soll. Sie sollten sich niemals auf den Garbage Collector verlassen. Die docs noch sagen:

Streams haben eine BaseStream.close() Methode und implementieren AutoCloseable. Wenn Sie nach dem Schließen auf einem Stream arbeiten, wird IllegalStateException geworfen. Die meisten Stream-Instanzen müssen nach der Verwendung nicht wirklich geschlossen werden, da sie durch Sammlungen, Arrays oder Generierungsfunktionen unterstützt werden, für die keine spezielle Ressourcenverwaltung erforderlich ist. Im Allgemeinen müssen nur Datenströme geschlossen werden, deren Quelle ein E/A-Kanal ist, z. B. die von Files.lines(Path) zurückgegebenen Datenströme. Wenn ein Stream geschlossen werden muss, muss er als Ressource in einer Try-with-resources-Anweisung oder einer ähnlichen Kontrollstruktur geöffnet werden, um sicherzustellen, dass er sofort geschlossen wird, nachdem seine Operationen abgeschlossen wurden.

5

Der Aufruf von spliterator() Verfahren auch eine Spliterator für die Elemente dieses Stroms und gibt dessen ein Terminalbetrieb.

Um Ihre Frage zu beantworten - Nein, die spliterator Verfahren oder für diese Sake keinen der anderen Operationen auch nicht schließen lassen den Strom.

Diese steht dokumentiert für terminal operations as -

Nachdem der Terminalbetrieb durchgeführt wird, die Stream-Pipeline wird verbraucht betrachtet und nicht mehr verwendet werden können .... In fast allen Fällen, Terminalbetrieb sind eifrig, ihre Durchquerung der Datenquelle und Verarbeitung der Pipeline vor der Rückkehr abgeschlossen. Nur die Terminals Operationen iterator() und spliterator() sind nicht; Diese werden als eine "Escape-Luke" zur Verfügung gestellt, um beliebige clientgesteuerte Pipeline-Traversalen für den Fall zu ermöglichen, dass die vorhandenen Operationen ausreichen, um die Aufgabe.

über die Stream auf einer anderen Hand geschlossenen Zustand die docs, dass: -

meisten Strom Instanzen tatsächlich brauchen nicht nach Gebrauch verschlossen werden, da sie durch Sammlungen gesichert sind, Arrays oder Erzeugen Funktionen, die erfordern keine spezielle Ressourcenverwaltung. Im Allgemeinen werden nur Datenströme, deren Quelle ein E/A-Kanal ist, z. B. die von Files.lines(Path), zurückgegebenen Daten, geschlossen.


Die AutoCloseable Staaten passen für eine Basisklasse it-

Es ist möglich, und in der Tat üblich, AutoCloseable obwohl nicht alle seine Unterklassen oder Instanzen zu implementieren wird halten freisetzbare Ressourcen.

das ist, wie die Base es erstreckt und die close() wirkt sich nicht auf weit mehr als die Ströme über die, die die Ressourcen wie Files.lines(...) verwenden.

Wenn jedoch Einrichtungen wie Stream verwenden, die beide unterstützen I/O-basierte und nicht-I/O-basierte Formulare, versuchen-with-Ressourcen-Blöcke sind in allgemeinen unnötig bei der Verwendung von nicht-I/O-basierte Formulare.

Verwandte Themen