Duplicata possible :
Pourquoi l'Iterator de Java n'est-il pas un Iterable ?Comment utiliser la boucle for-each de manière idiomatique avec un itérateur ?
Peut-on utiliser la boucle for-each pour itérer les objets de type Iterator ?
Les boucles foreach sont, pour autant que je sache, du sucre syntaxique ajouté dans Java 5. Ainsi, les boucles foreach sont des syntaxes ajoutées à Java 5, à ma connaissance.
Iterable<O> iterable;
for(O o : iterable) {
// Do something
}
produira essentiellement le même bytecode que
Iterable<O> iterable;
for(Iterator<O> iter = iterable.iterator(); iter.hasNext(); /* NOOP */) {
O o = iter.next();
// Do something
}
Cependant, si je n'ai pas d'itérable en premier lieu, mais seulement un itérateur (par exemple, parce qu'une classe offre deux itérateurs différents), je ne peux pas utiliser la boucle foreach de la syntaxe du sucre. Évidemment, je peux toujours faire l'itération à l'ancienne. Cependant, j'aimerais en fait faire :
Iterator<O> iter;
for(O o : iter /* Iterator<O>, not Iterable<O>! */) {
// Do something
}
Et bien sûr, je peux faire un faux Iterable
:
class Adapter<O> implements Iterable<O> {
Iterator<O> iter;
public Adapter(Iterator<O> iter) {
this.iter = iter;
}
@Override
public Iterator<O> iterator() {
return iter;
}
}
(Ce qui, en fait, est une utilisation abusive de l'API Iterable, puisqu'il ne peut être itéré qu'une seule fois).
S'il était conçu autour de Iterator
au lieu de itérable, on pourrait faire un certain nombre de choses intéressantes :
for(O o : iterable.iterator()) {} // Iterate over Iterable and Collections
for(O o : list.backwardsIterator()) {} // Or backwards
Iterator<O> iter;
for(O o : iter) {
if (o.something()) { iter.remove(); }
if (o.something()) { break; }
}
for(O : iter) { } // Do something with the remaining elements only.
Quelqu'un sait-il pourquoi la langue a été conçue de cette façon ? Pour éviter toute ambiguïté si une classe implémentait à la fois Iterator
y Iterable
? Pour éviter les erreurs de programmation qui supposent que "for(O o : iter)" traitera tous les éléments deux fois (et oubliera d'obtenir un nouvel itérateur) ? Ou y a-t-il une autre raison à cela ?
Ou existe-t-il une astuce linguistique que je ne connais pas ?