简体   繁体   English

为什么我不能在 Java 枚举上使用 foreach?

[英]Why can't I use foreach on Java Enumeration?

Why can't I do:为什么我不能这样做:

Enumeration e = ...
for (Object o : e)
  ...

Because Enumeration<T> doesn't extend Iterable<T> .因为Enumeration<T>不扩展Iterable<T> Here is an example of making Iterable Enumerations .这是制作可迭代枚举示例

As to why that's an interesting question.至于为什么这是一个有趣的问题。 This isn't exactly your question but it sheds some light on it.这不完全是您的问题,但它对此有所了解。 From the Java Collections API Design FAQ :来自Java 集合 API 设计常见问题解答

Why doesn't Iterator extend Enumeration?为什么迭代器不扩展枚举?

We view the method names for Enumeration as unfortunate.我们认为 Enumeration 的方法名称很不幸。 They're very long, and very frequently used.它们很长,而且使用频率很高。 Given that we were adding a method and creating a whole new framework, we felt that it would be foolish not to take advantage of the opportunity to improve the names.鉴于我们正在添加一个方法并创建一个全新的框架,我们认为不利用这个机会改进名称是愚蠢的。 Of course we could support the new and old names in Iterator, but it doesn't seem worthwhile.当然我们可以在Iterator中支持新旧名称,但似乎不值得。

That basically suggests to me that Sun wants to distance themselves from Enumeration, which is very early Java with quite a verbose syntax.这基本上向我表明,Sun 希望与 Enumeration 保持距离,Enumeration 是非常早期的 Java,具有相当冗长的语法。

Using Collections utility class, Enumeration can be made iterable like:使用 Collections 实用程序类,可以使枚举可迭代,例如:

Enumeration headerValues=request.getHeaders("mycustomheader");
List headerValuesList=Collections.list(headerValues);

for(Object headerValueObj:headerValuesList){
 ... do whatever you want to do with headerValueObj
}

I have solved this problem with two very simple classes, one for Enumeration and one for Iterator .我用两个非常简单的类解决了这个问题,一个用于Enumeration ,一个用于Iterator The enumeration wrapper is as follows:枚举包装器如下:

static class IterableEnumeration<T>
extends Object
implements Iterable<T>, Iterator<T>
{
private final Enumeration<T>        enumeration;
private boolean                     used=false;

IterableEnumeration(final Enumeration<T> enm) {
    enumeration=enm;
    }

public Iterator<T> iterator() {
    if(used) { throw new IllegalStateException("Cannot use iterator from asIterable wrapper more than once"); }
    used=true;
    return this;
    }

public boolean hasNext() { return enumeration.hasMoreElements(); }
public T       next()    { return enumeration.nextElement();     }
public void    remove()  { throw new UnsupportedOperationException("Cannot remove elements from AsIterator wrapper around Enumeration"); }
}

Which can be used either with a static utility method (which is my preference):可以与静态实用程序方法一起使用(这是我的偏好):

/**
 * Convert an `Enumeration<T>` to an `Iterable<T>` for a once-off use in an enhanced for loop.
 */
static public <T> Iterable<T> asIterable(final Enumeration<T> enm) {
    return new IterableEnumeration<T>(enm);
    }

...

for(String val: Util.asIterable(enm)) {
    ...
    }

or by instantiating the class:或通过实例化类:

for(String val: new IterableEnumeration<String>(enm)) {
    ...
    }

The new-style-for-loop ("foreach") works on arrays, and things that implement the Iterable interface.新式 for 循环(“foreach”)适用于数组和实现Iterable接口的事物。

It's also more analogous to Iterator than to Iterable , so it wouldn't make sense for Enumeration to work with foreach unless Iterator did too (and it doesn't).它也更类似于Iterator不是Iterable ,因此Enumeration与 foreach 一起工作是没有意义的,除非Iterator也这样做(并且它没有)。 Enumeration is also discouraged in favor of Iterator . Enumeration也不鼓励使用Iterator

With java 8 and beyond this is possible:使用 java 8 及更高版本,这是可能的:

import java.util.Collections;
import java.util.Enumeration;

Enumeration e = ...;
Collections.list(e).forEach(o -> {
    ... // use item "o"
});

Enumeration doesn't implement Iterable and as such can't be used directly in a foreach loop. Enumeration不实现Iterable ,因此不能直接在 foreach 循环中使用。 However using Apache Commons Collections it's possible to iterate over an enumeration with:但是,使用Apache Commons Collections可以通过以下方式迭代枚举:

for (Object o : new IteratorIterable(new EnumerationIterator(e))) {
    ...
}

You could also use a shorter syntax with Collections.list() but this is less efficient (two iterations over the elements and more memory usage) :您也可以在Collections.list()使用更短的语法,但这效率较低(元素上的两次迭代和更多的内存使用):

for (Object o : Collections.list(e))) {
    ...
}

Because an Enumeration (and most classes derived from this interface) does not implement Iterable.因为枚举(以及从该接口派生的大多数类)没有实现 Iterable。

You can try to write your own wrapper class.您可以尝试编写自己的包装类。

We can use the for loop to iterate over an enumeration using the .values​​()我们可以使用 for 循环使用.values​​()迭代枚举

method which returns all the elements contained in the enumeration. method which returns all the elements contained in the enumeration.

An example :一个例子 :

for (USERS_ROLES userRole: USERS_ROLES .values ​​()) {
            System.out.println ("This is one user role:" + userRole.toString ());
}

I did it in java 10我在java 10中做到了

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM