泛型枚举到可迭代转换器

发布于 2024-12-17 04:30:40 字数 1539 浏览 0 评论 0原文

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

染墨丶若流云 2024-12-24 04:30:40

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

java.util.Collections has a list method that copies an Enumeration into a List, which you can then use in a for-each loop (see javadoc).

狼亦尘 2024-12-24 04:30:40

这是 javadoc 关于枚举到迭代器(不可迭代)的转换:

公共静态不可修改迭代器
forEnumeration(Enumeration枚举)

使枚举适应迭代器接口。

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

此外,Apache Commons Collections 当前的实现不支持 Java 5 功能和 API(例如 Iterable),因此没有机会。

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

例如,使用 EnumerationUtils.toList(枚举)

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

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

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。在查看代码时,这并不是立即显而易见的,并且可能是导致许多令人沮丧的错误的原因。因此,我认为不存在这种实用方法是有道理的。

Here is the javadoc from Guava regarding the conversion of an Enumeration to Iterator (not iterable):

public static UnmodifiableIterator
forEnumeration(Enumeration enumeration)

Adapts an Enumeration to the Iterator interface.

This method has no equivalent in Iterables because viewing an
Enumeration as an Iterable is impossible. However, the contents can be
copied into a collection using
Collections.list(java.util.Enumeration).

Further more apache commons collections current implementation doesn't support Java 5 features and APIs such as Iterable, so there's no chance there.

There are however some methods in those libraries which allow you to change an enumeration to a collection which is iterable and use that (they do implicitly copy your data though).

For instance, transform to a list with EnumerationUtils.toList(enumeration).

Edit: Due to some queries in the question, I'll try and summarize why the makers of guava (and I) don't feel an enumeration can be made into an iterable.

An iterable creates iterator instances, someone reading the code (or API) can assume that each call to iterator() yields a new iterator instance starting the enumeration from the first element. If we do a simple conversion between an iterator (or enumeration) and an iterable then the user of the API needs to know that a call to iterator() changes the state of the object and that 2 consecutive calls might behave oddly. here is an example:

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;

If implemented as a simple conversion ( O(1) ) The above method behaves differently for different inputs: ["hello","world"] would return true, while ["world","hello"] would return false. This is not immediately apparent when looking at the code and can be the cause for many frustrating bugs. Therefore, I believe it makes sense to not have this utility method exist.

素染倾城色 2024-12-24 04:30:40

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

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());

In my opinion the documented way is the simplest so there is no need to converting into 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());
沩ん囻菔务 2024-12-24 04:30:40

看一下这篇文章: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();
                  }
              };
          }
      };
  }    
}

Take a look on this article: http://www.java2s.com/Code/Java/Collections-Data-Structure/TreatanEnumerationasanIterable.htm

It seems exactly what you need.

UPDATED
Added the code for future reference in case the link would become broken.

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();
                  }
              };
          }
      };
  }    
}
(り薆情海 2024-12-24 04:30:40

您有两种解决方案:

第一种是将枚举器消耗到可迭代的集合中(如@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 对象创建的迭代器上进行多次迭代。

You have two solutions:

First is to consume the enumerator into a collection that is Iterable(as described by @skaffman). This will add O(n) as noted by @Michael

In cases that you have access to the method that created the enumerator you can wrap this into an Iterable without paying the cost. In your case you can create a Iterable with:

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"))
    }
}

In this cases you can iterate multiple times on the Iterators created by the Iterable objects.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文