In Java 8 haben wir die Klasse Stream <T> , die seltsamerweise eine Methode hat
Iterator<T> iterator()
Sie würden also erwarten, dass die Schnittstelle Iterable <T> implementiert wird , was genau diese Methode erfordert, aber das ist nicht der Fall.
Wenn ich mit einer foreach-Schleife über einen Stream iterieren möchte, muss ich so etwas tun
public static Iterable<T> getIterable(Stream<T> s) {
return new Iterable<T> {
@Override
public Iterator<T> iterator() {
return s.iterator();
}
};
}
for (T element : getIterable(s)) { ... }
Vermisse ich hier etwas?
java
java-8
java-stream
iterable
roim
quelle
quelle
Stream
an ältere APIs zu übergeben, die erwartenIterable
getIterable()
zureturn s::iterator;
for (T element : stream::iterator)
, daher würde ich es immer noch vorziehen, wenn Stream auchIterable
eine Methode implementieren würdetoIterable()
.Antworten:
Die Leute haben das schon auf der Mailingliste gefragt ☺. Der Hauptgrund dafür ist, dass Iterable auch eine wiederholbare Semantik hat, Stream jedoch nicht.
quelle
Iterable
darüber, obiterator
immer mehrmals aufgerufen werden soll oder nicht. Das sollten sie da reinstecken. Dies scheint eher eine Standardpraxis als eine formale Spezifikation zu sein.Um ein
Stream
in ein zu konvertierenIterable
, können Sie tunUm a
Stream
an eine Methode zu übergeben, die erwartetIterable
,einfach
aber es sieht wahrscheinlich lustig aus; es könnte besser sein, ein bisschen expliziter zu sein
quelle
for(X x : (Iterable<X>)stream::iterator)
, obwohl es hässlich aussieht. Wirklich, die ganze Situation ist einfach absurd.IntStream.range(0,N).forEach(System.out::println)
stream::iterator
undstream.iterator()
, was das erstere für einIterable
aber nicht das letztere akzeptabel macht ?Iterable
ist eine funktionale Schnittstelle, daher reicht es aus, eine Funktion zu übergeben, die sie implementiert.Ich möchte darauf hinweisen, dass
StreamEx
diesIterable
(undStream
) implementiert , sowie eine Vielzahl anderer immens beeindruckender Funktionen, die fehlenStream
.quelle
Sie können einen Stream in einer
for
Schleife wie folgt verwenden:(Führen Sie dieses Snippet hier aus )
(Dies verwendet eine Java 8-Funktionsschnittstelle.)
(Dies wird in einigen der obigen Kommentare behandelt (z. B. Aleksandr Dubinsky ), aber ich wollte es in eine Antwort ziehen, um es sichtbarer zu machen.)
quelle
kennytm beschrieb, warum es unsicher ist, a
Stream
als zu behandelnIterable
, und Zhong Yu bot eine Problemumgehung an , die die Verwendung einesStream
as in ermöglichtIterable
, wenn auch auf unsichere Weise. Es ist möglich , das Beste aus beiden Welten zu bekommen: ein wiederverwendbarenIterable
von einemStream
, der durch die aus allen Garantien erfülltIterable
Spezifikation.Hinweis:
SomeType
ist hier kein Typparameter - Sie müssen ihn durch einen geeigneten Typ (z. B.String
) ersetzen oder auf Reflexion zurückgreifenEs gibt einen großen Nachteil:
Die Vorteile der verzögerten Iteration gehen verloren. Wenn Sie vorhaben, alle Werte im aktuellen Thread sofort zu durchlaufen, ist der Overhead vernachlässigbar. Wenn Sie jedoch nur teilweise oder in einem anderen Thread iterieren möchten, kann diese sofortige und vollständige Iteration unbeabsichtigte Folgen haben.
Der große Vorteil ist natürlich, dass Sie das wiederverwenden können
Iterable
, während(Iterable<SomeType>) stream::iterator
es nur eine einmalige Verwendung erlauben würde. Wenn der empfangende Code mehrmals über die Sammlung iteriert, ist dies nicht nur erforderlich, sondern wahrscheinlich auch vorteilhaft für die Leistung.quelle
Stream.toArray()
Gibt ein Array zurück, keinIterable
, daher wird dieser Code immer noch nicht kompiliert. aber es kann ein Fehler in Eclipse sein, da IntelliJ es zu kompilieren scheintStream
nicht implementiertIterable
. Das allgemeine Verständnis vonIterable
ist alles, worauf oft wiederholt werden kann.Stream
ist möglicherweise nicht wiederholbar.Die einzige Problemumgehung, die ich mir vorstellen kann, wenn ein auf einem Stream basierendes Iterable ebenfalls wiedergegeben werden kann, besteht darin, den Stream neu zu erstellen. Ich verwende
Supplier
unten, um eine neue Instanz des Streams zu erstellen, jedes Mal, wenn ein neuer Iterator erstellt wird.quelle
Wenn es Ihnen nichts ausmacht, Bibliotheken von Drittanbietern zu verwenden, definiert cyclops-react einen Stream, der sowohl Stream als auch Iterable implementiert und auch wiedergegeben werden kann (Lösung des beschriebenen Kennytm- Problems ).
oder :-
[Offenlegung Ich bin der Hauptentwickler von Cyclops-React]
quelle
Nicht perfekt, wird aber funktionieren:
Nicht perfekt, weil es alle Elemente aus dem Stream abruft und in das einfügt
List
, was nicht genau das istIterable
und worumStream
es geht. Sie sollen faul sein .quelle
Sie können alle Dateien in einem Ordner folgendermaßen durchlaufen
Stream<Path>
:quelle