通用枚举到Iterable转换器

IAd*_*ter 34 java collections open-source enumerable

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

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

ska*_*man 45

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


Asa*_*saf 16

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

public static UnmodifiableIterator forEnumeration(Enumeration enumeration)

将枚举适配到Iterator接口.

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

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

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

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

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

迭代创建迭代器实例,读取代码(或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;
Run Code Online (Sandbox Code Playgroud)

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

  • 关于番石榴"不可能"主张的愚蠢之处在于我们实际上已经在我们的实用方法中实现了这个"不可能"的Iterable.因为我们将方法调用为SingleUseIterable(),所以调用者很明显它只能工作一次. (7认同)

Kra*_*uss 8

在我看来,记录的方式是最简单的,所以不需要转换为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());
Run Code Online (Sandbox Code Playgroud)


Ale*_*exR 5

看看这篇文章: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();
                  }
              };
          }
      };
  }    
}
Run Code Online (Sandbox Code Playgroud)

  • 不,那根本不是我需要的。正如我所说,编写这段代码很容易,但这不是我想要的。 (3认同)
  • 该代码的问题在于,通过 Iterable 创建的所有迭代器都将使用相同的枚举器。 (2认同)