Diese Antwort bietet bereits eine Lösung, die Stream
aus einem Enumeration
:
public static <T> Stream<T> enumerationAsStream(Enumeration<T> e) {
return StreamSupport.stream(
Spliterators.spliteratorUnknownSize(
new Iterator<T>() {
public T next() {
return e.nextElement();
}
public boolean hasNext() {
return e.hasMoreElements();
}
},
Spliterator.ORDERED), false);
}
Es sollte betont werden , dass die resultierende Stream
ist wie jede andere als faul Stream
, da es keine Produkte verarbeiten , bevor das Terminal Aktion begonnen wurde , und wenn die Terminalbetrieb Kurzschluss ist, wird es nur so viele Punkte wie nötig wiederholen.
Dennoch gibt es Raum für Verbesserungen. Ich würde immer eine forEachRemaining
Methode hinzufügen , wenn es eine einfache Möglichkeit gibt, alle Elemente zu verarbeiten. Diese Methode wird von der Stream
Implementierung für die meisten nicht kurzgeschlossenen Operationen aufgerufen :
public static <T> Stream<T> enumerationAsStream(Enumeration<T> e) {
return StreamSupport.stream(
Spliterators.spliteratorUnknownSize(
new Iterator<T>() {
public T next() {
return e.nextElement();
}
public boolean hasNext() {
return e.hasMoreElements();
}
public void forEachRemaining(Consumer<? super T> action) {
while(e.hasMoreElements()) action.accept(e.nextElement());
}
},
Spliterator.ORDERED), false);
}
Der obige Code ist jedoch ein Opfer des Iterator
Antipatterns "Verwenden, weil es so vertraut ist". Das erstellte Iterator
wird in eine Implementierung der neuen Spliterator
Schnittstelle eingebunden und bietet keinen Vorteil gegenüber der Spliterator
direkten Implementierung :
public static <T> Stream<T> enumerationAsStream(Enumeration<T> e) {
return StreamSupport.stream(
new Spliterators.AbstractSpliterator<T>(Long.MAX_VALUE, Spliterator.ORDERED) {
public boolean tryAdvance(Consumer<? super T> action) {
if(e.hasMoreElements()) {
action.accept(e.nextElement());
return true;
}
return false;
}
public void forEachRemaining(Consumer<? super T> action) {
while(e.hasMoreElements()) action.accept(e.nextElement());
}
}, false);
}
Auf der Quellcode-Ebene ist diese Implementierung so einfach wie die Iterator
-basierte, eliminiert jedoch die Delegierung von a Spliterator
nach a Iterator
. Die Leser müssen lediglich die neue API kennenlernen.