This answer 已经提供了一个解决方案,可以从Enumeration 创建一个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();
}
},
Spliterator.ORDERED), false);
}
应该强调的是,生成的Stream 是 与任何其他Stream 一样懒惰,因为它不会在终端操作开始之前处理任何项目,如果终端操作是短路的,它只会迭代尽可能多的项目。
不过,它还有改进的余地。当有一种直接的方式来处理所有元素时,我总是会添加一个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 相比没有任何优势:
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 一样简单,但消除了从Spliterator 到Iterator 的委托。它只要求读者了解新的 API。