通用枚举到Iterable转换器

HttpServletRequest使用了很多java.util.Enumeration。 我想在for-each中使用它们,所以我需要将它们转换为可交换的。 这不是问题,但由于我有多个项目需要这个,我需要一个库才能做到这一点。 我宁愿不做自己的 – 有没有支持这种装饰的标准库?

是否有内置构造将枚举转换为Iterable?

java.util.Collections有一个list方法,它将Enumeration复制到List ,然后你可以在for-each循环中使用它(参见javadoc )。

这是来自Guava的关于将Enumeration转换为Iterator(不可迭代)的javadoc :

public static UnmodifiableIterator forEnumeration(Enumeration enumeration)

将枚举适配到Iterator接口。

此方法在Iterables中没有等价物,因为将枚举视为Iterable是不可能的。 但是,可以使用Collections.list(java.util.Enumeration)将内容复制到集合中。

更多的apache commons集合当前的实现不支持Java 5的function和API,例如Iterable,所以没有机会。

但是,这些库中有一些方法允许您将枚举更改为可迭代的集合并使用它(它们会隐式复制您的数据)。

例如,使用EnumerationUtils.toList(枚举)转换为列表。

编辑:由于问题中的一些问题,我将尝试总结为什么番石榴(和我)的制造者不觉得枚举可以变成可迭代的。

迭代创建迭代器实例,读取代码(或API)的人可以假设每次调用iterator()都会产生一个新的迭代器实例,从第一个元素开始枚举。 如果我们在迭代器(或枚举)和iterable之间进行简单转换,那么API的用户需要知道对iterator()的调用会改变对象的状态,并且2个连续的调用可能表现得很奇怪。 这是一个例子:

 Iterable iter = magicFunction(enumeration); for (String s : iter) { if ("hello".equals(s)) break; } for (String s : iter) { if ("world".equals(s)) return true; } return false; 

如果实现为简单转换(O(1))上述方法对于不同的输入表现不同: ["hello","world"]将返回true ,而["world","hello"]将返回false 。 在查看代码时,这并不是立即显而易见的,并且可能是许多令人沮丧的错误的原因。 因此,我认为没有这种实用方法存在是有道理的。

在我看来,记录的方式是最简单的,所以不需要转换为Iterator:

https://docs.oracle.com/javase/1.5.0/docs/api/java/util/Enumeration.html

 for (Enumeration e = v.elements(); e.hasMoreElements();) System.out.println(e.nextElement()); 

看一下这篇文章: http : //www.java2s.com/Code/Java/Collectionsvant-Structure/TreatanEnumerationasanIterable.htm

这似乎正是你所需要的。

更新添加了代码以供将来参考,以防链接被破坏。

 import java.util.Enumeration; import java.util.Iterator; /** * @since 4.37 * @author Jaroslav Tulach */ public class Utils { public static  Iterable iterable(final Enumeration enumeration) { if (enumeration == null) { throw new NullPointerException(); } return new Iterable() { public Iterator iterator() { return new Iterator() { public boolean hasNext() { return enumeration.hasMoreElements(); } public E next() { return enumeration.nextElement(); } public void remove() { throw new UnsupportedOperationException(); } }; } }; } } 

你有两个解决方案:

首先是将枚举器用于Iterable的集合(如@skaffman所述)。 如@Michael所述,这将添加O(n)

如果您有权访问创建枚举器的方法,则可以将其包装到Iterable中而无需支付费用。 在您的情况下,您可以创建一个Iterable:

 final Request request2 = request; Iterable headerNamesIterable = new Iterable(){ public Iterator iterator(){ return Iterators.forEnumeration(request2.getHeaderNames()) } } Iterable headersIterableName1 = new Iterable(){ public Iterator iterator(){ return Iterators.forEnumeration(request2.getHeaders("name1")) } } 

在这种情况下,您可以在Iterable对象创建的迭代器上多次迭代。