Ответ 1
Этот ответ уже предоставляет решение, которое создает Stream
из 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); }
Следует подчеркнуть, что результирующий Stream
является таким же ленивым, как и любой другой Stream
, поскольку он не будет обрабатывать какие-либо элементы до того, как действие терминала будет начато, и, если операция терминала имеет короткое замыкание, он будет повторять только столько элементов, сколько необходимо.
Тем не менее, у него есть возможности для улучшения. forEachRemaining
всегда добавляю метод forEachRemaining
когда существует простой способ обработки всех элементов. Указанный метод будет вызываться реализацией Stream
для большинства операций без короткого замыкания:
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);
}
Однако приведенный выше код является жертвой антипаттерна "использующий Iterator
потому что он так знаком". Созданный Iterator
будет Spliterator
в реализацию нового интерфейса Spliterator
и не дает никаких преимуществ по Spliterator
прямой реализацией Spliterator
:
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);
}
На уровне исходного кода эта реализация так же проста, как Iterator
-based, но исключает делегирование Spliterator
Iterator
. Это только требует, чтобы его читатели узнали о новом API.