1. 概述
Enumeration是Java第一个版本(JDK 1.0)中引入的一个接口。此接口是泛型的,并提供对元素序列的惰性访问。尽管在较新版本的Java中有更好的替代方案,但遗留实现可能仍会使用Enumeration接口返回结果。因此,为了使遗留实现现代化,开发人员可能必须将Enumeration对象转换为Java Stream API。
在这个简短的教程中,我们将实现一个实用程序方法,用于将Enumeration对象转换为Java Stream API。因此,我们将能够使用流方法,例如filter和map。
2. Java的Enumeration接口
让我们从一个例子开始来说明Enumeration对象的使用:
public static <T> void print(Enumeration<T> enumeration) {
while (enumeration.hasMoreElements()) {
System.out.println(enumeration.nextElement());
}
}
Enumeration有两个主要方法:hasMoreElements和nextElement。我们应该同时使用这两种方法来迭代元素集合。
3. 创建Spliterator
作为第一步,我们将为AbstractSpliterator抽象类创建一个具体类。此类是使Enumeration对象适应Spliterator接口所必需的:
public class EnumerationSpliterator<T> extends AbstractSpliterator<T> {
private final Enumeration<T> enumeration;
public EnumerationSpliterator(long est, int additionalCharacteristics, Enumeration<T> enumeration) {
super(est, additionalCharacteristics);
this.enumeration = enumeration;
}
}
除了创建类,我们还需要创建一个构造函数。我们应该将前两个参数传递给父类构造函数。第一个参数是Spliterator的估计大小。第二个用于定义附加特征。最后,我们将使用最后一个参数来接收Enumeration对象。
我们还需要覆盖tryAdvance和forEachRemaining方法。Stream API将使用它们对Enumeration的元素执行操作:
@Override
public boolean tryAdvance(Consumer<? super T> action) {
if (enumeration.hasMoreElements()) {
action.accept(enumeration.nextElement());
return true;
}
return false;
}
@Override
public void forEachRemaining(Consumer<? super T> action) {
while (enumeration.hasMoreElements())
action.accept(enumeration.nextElement());
}
4. Enumeration转化为Stream
现在,使用EnumerationSpliterator类,我们可以使用StreamSupport API来执行转换:
public static <T> Stream<T> convert(Enumeration<T> enumeration) {
EnumerationSpliterator<T> spliterator = new EnumerationSpliterator<T>(Long.MAX_VALUE, Spliterator.ORDERED, enumeration);
Stream<T> stream = StreamSupport.stream(spliterator, false);
return stream;
}
在此实现中,我们需要创建EnumerationSpliterator类的实例。Long.MAX_VALUE是估计大小的默认值。Spliterator.ORDERED定义流将按照枚举提供的顺序迭代元素。
接下来,我们应该从StreamSupport类调用stream方法。我们需要将EnumerationSpliterator实例作为第一个参数传递,最后一个参数是定义流是并行的还是顺序的。
5. 测试我们的实现
通过测试我们的convert方法,我们可以观察到现在我们能够基于Enumeration创建一个有效的Stream对象:
@Test
public void givenEnumeration_whenConvertedToStream_thenNotNull() {
Vector<Integer> input = new Vector<>(Arrays.asList(1, 2, 3, 4, 5));
Stream<Integer> resultingStream = convert(input.elements());
Assert.assertNotNull(resultingStream);
}
6. 总结
在本教程中,我们展示了如何将Enumeration转换为Stream对象。
与往常一样,本教程的完整源代码可在GitHub上获得。