Why can't I use foreach on Java Enumeration?

JavaLoops

Java Problem Overview


Why can't I do:

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

Java Solutions


Solution 1 - Java

Because Enumeration<T> doesn't extend 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:

> Why doesn't Iterator extend Enumeration? > > We view the method names for > Enumeration as unfortunate. 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.

That basically suggests to me that Sun wants to distance themselves from Enumeration, which is very early Java with quite a verbose syntax.

Solution 2 - Java

Using Collections utility class, Enumeration can be made iterable like:

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

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

Solution 3 - Java

I have solved this problem with two very simple classes, one for Enumeration and one for 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)) {
    ...
    }

Solution 4 - Java

The new-style-for-loop ("foreach") works on arrays, and things that implement the Iterable interface.

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). Enumeration is also discouraged in favor of Iterator.

Solution 5 - Java

With java 8 and beyond this is possible:

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

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

Solution 6 - Java

Enumeration doesn't implement Iterable and as such can't be used directly in a foreach loop. However using Apache Commons Collections it's possible to iterate over an enumeration with:

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) :

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

Solution 7 - Java

Because an Enumeration (and most classes derived from this interface) does not implement Iterable.

You can try to write your own wrapper class.

Solution 8 - Java

We can use the for loop to iterate over an enumeration using the .values​​()

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionripper234View Question on Stackoverflow
Solution 1 - JavacletusView Answer on Stackoverflow
Solution 2 - Javauser1555669View Answer on Stackoverflow
Solution 3 - JavaLawrence DolView Answer on Stackoverflow
Solution 4 - JavaLaurence GonsalvesView Answer on Stackoverflow
Solution 5 - JavaslartidanView Answer on Stackoverflow
Solution 6 - JavaEmmanuel BourgView Answer on Stackoverflow
Solution 7 - JavaStroboskopView Answer on Stackoverflow
Solution 8 - JavaAmede Angel AulerienView Answer on Stackoverflow