Pourquoi ne puis-je pas utiliser foreach sur Java Enumeration?

Pourquoi je ne peux pas faire:

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

Parce que l’ Enumeration ne prolonge pas Iterable . Voici un exemple de réalisation d’énumérations itérables .

Pourquoi est-ce une question intéressante? Ce n’est pas exactement votre question, mais elle nous éclaire. A partir de la FAQ sur la conception des API de Java Collections :

Pourquoi Iterator ne prolonge-t-il pas l’énumération?

Nous considérons que les noms de méthode pour énumération sont regrettables. Ils sont très longs et très fréquemment utilisés. Étant donné que nous étions en train d’append une méthode et de créer un nouveau cadre, nous avons pensé qu’il serait insensé de ne pas profiter de l’occasion pour améliorer les noms. Bien sûr, nous pourrions supporter les nouveaux et anciens noms dans Iterator, mais cela ne semble pas utile.

Cela me suggère essentiellement que Sun veut se démarquer de Enumeration, qui est très tôt Java avec une syntaxe assez verbeuse.

En utilisant la classe d’utilitaire Collections, l’énumération peut être rendue comme:

 Enumeration headerValues=request.getHeaders("mycustomheader"); List headerValuesList=Collections.list(headerValues); for(Object headerValueObj:headerValuesList){ ... do whatever you want to do with headerValueObj } 

J’ai résolu ce problème avec deux classes très simples, l’une pour l’ Enumeration et l’autre pour l’ Iterator . Le wrapper d’énumération est comme suit:

 static class IterableEnumeration extends Object implements Iterable, Iterator { private final Enumeration enumeration; private boolean used=false; IterableEnumeration(final Enumeration enm) { enumeration=enm; } public Iterator 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"); } } 

Qui peut être utilisé soit avec une méthode utilitaire statique (qui est ma préférence):

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

ou en instanciant la classe:

 for(Ssortingng val: new IterableEnumeration(enm)) { ... } 

Le nouveau style pour la boucle (“foreach”) fonctionne sur les tableaux et sur les éléments qui implémentent l’interface Iterable .

Il est également plus analogue à Iterator qu’à Iterable , de sorte qu’il ne serait pas logique que Enumeration fonctionne avec foreach à moins que l’ Iterator ne le fasse (et ce n’est pas le cas). Enumeration est également déconseillée en faveur de l’ Iterator .

Enumeration pas Iterable et ne peut donc pas être utilisée directement dans une boucle foreach. Cependant, en utilisant Apache Commons Collections, il est possible de parcourir une énumération avec:

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

Vous pourriez également utiliser une syntaxe plus courte avec Collections.list() mais ceci est moins efficace (deux itérations sur les éléments et plus d’utilisation de la mémoire):

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

Parce qu’une énumération (et la plupart des classes dérivées de cette interface) n’implémente pas Iterable.

Vous pouvez essayer d’écrire votre propre classe wrapper.