通用枚举到Iterable转换器

时间:2011-11-19 22:17:41

标签: java collections open-source enumerable

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

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

5 个答案:

答案 0 :(得分:43)

java.util.Collectionslist方法可将Enumeration复制到List,然后您可以在for-each循环中使用该方法(请参阅javadoc )。

答案 1 :(得分:16)

以下是Guava关于将枚举转换为迭代器(不可迭代)的javadoc

  

public static UnmodifiableIterator   forEnumeration(Enumeration enumeration)

     

将枚举适配到Iterator接口。

     

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

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

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

例如,转换为EnumerationUtils.toList(enumeration)的列表。

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

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

Iterable<String> 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 。在查看代码时,这并不是很明显,并且可能是造成许多令人沮丧的错误的原因。因此,我认为不存在这种实用方法是有道理的。

答案 2 :(得分:6)

在我看来,记录的方式是最简单的,因此无需转换为Iterator:

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

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

答案 3 :(得分:3)

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

这似乎正是你所需要的。

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

import java.util.Enumeration;
import java.util.Iterator;

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

答案 4 :(得分:2)

您有两种解决方案:

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

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

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

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

相关问题