Comme d'autres l'ont dit, un Iterable peut être appelé plusieurs fois, renvoyant un nouvel Iterator à chaque appel; un itérateur n'est utilisé qu'une seule fois. Ils sont donc liés, mais servent des objectifs différents. Malheureusement, la méthode «compact pour» ne fonctionne qu'avec un itérable.
Ce que je décrirai ci-dessous est une façon d'avoir le meilleur des deux mondes - renvoyer un Iterable (pour une syntaxe plus agréable) même lorsque la séquence de données sous-jacente est unique.
L'astuce consiste à renvoyer une implémentation anonyme de l'itérable qui déclenche réellement le travail. Ainsi, au lieu de faire le travail qui génère une séquence ponctuelle puis de renvoyer un Iterator dessus, vous retournez un Iterable qui, chaque fois qu'il est accédé, refait le travail. Cela peut sembler un gaspillage, mais souvent vous n'appelerez l'itérable qu'une seule fois de toute façon, et même si vous l'appelez plusieurs fois, il a toujours une sémantique raisonnable (contrairement à un simple wrapper qui fait qu'un Iterator "ressemble" à un Iterable, cela a gagné ' t échouer s'il est utilisé deux fois).
Par exemple, disons que j'ai un DAO qui fournit une série d'objets à partir d'une base de données, et que je veux donner accès à cela via un itérateur (par exemple pour éviter de créer tous les objets en mémoire s'ils ne sont pas nécessaires). Maintenant, je pourrais simplement retourner un itérateur, mais cela rend l'utilisation de la valeur retournée dans une boucle moche. Donc, à la place, j'emballe tout dans un Iterable anon:
class MetricDao {
...
/**
* @return All known metrics.
*/
public final Iterable<Metric> loadAll() {
return new Iterable<Metric>() {
@Override
public Iterator<Metric> iterator() {
return sessionFactory.getCurrentSession()
.createQuery("from Metric as metric")
.iterate();
}
};
}
}
cela peut ensuite être utilisé dans un code comme celui-ci:
class DaoUser {
private MetricDao dao;
for (Metric existing : dao.loadAll()) {
// do stuff here...
}
}
ce qui me permet d'utiliser la boucle for compacte tout en conservant l'utilisation de la mémoire incrémentielle.
Cette approche est «paresseuse» - le travail n'est pas fait lorsque l'itérable est demandé, mais seulement plus tard lorsque le contenu est répété - et vous devez être conscient des conséquences de cela. Dans l'exemple avec un DAO, cela signifie itérer sur les résultats dans la transaction de base de données.
Il y a donc plusieurs mises en garde, mais cela peut encore être un idiome utile dans de nombreux cas.