Un itérateur ne correspond pas nécessairement à quelque chose avec un "décompte" ...
Oliver Charlesworth
Les itérateurs sont ce qu'ils sont; pour itérer vers l'objet suivant d'une collection (cela peut être quelque chose comme set, array, etc.) Pourquoi ont-ils besoin de dire la taille quand ils ne se soucient pas de ce qu'ils essaient d'itérer? to provide an implementation-independent method for access, in which the user does not need to know whether the underlying implementation is some form of array or of linked list, and allows the user go through the collection without explicit indexing.penguin.ewu.edu/~trolfe/LinkedSort/Iterator.html
ecle
Réponses:
67
Si vous avez juste l'itérateur, c'est ce que vous devrez faire - il ne sait pas combien d'éléments il reste à parcourir, vous ne pouvez donc pas l'interroger pour ce résultat. Il existe des méthodes utilitaires qui semblent faire cela (comme Iterators.size()dans Guava), mais en dessous, elles effectuent à peu près la même opération.
Cependant, de nombreux itérateurs proviennent de collections, que vous pouvez souvent interroger pour leur taille. Et s'il s'agit d'une classe créée par l'utilisateur pour laquelle vous obtenez l'itérateur, vous pouvez chercher à fournir une méthode size () sur cette classe.
En bref, dans la situation où vous n'avez que l'itérateur, il n'y a pas de meilleur moyen, mais le plus souvent, vous avez accès à la collection ou à l'objet sous-jacent à partir duquel vous pourrez peut-être obtenir directement la taille.
Attention à l'effet secondaire de Iterators.size(...)(mentionné dans d'autres commentaires ci-dessous et dans java-doc): "Renvoie le nombre d'éléments restants dans l'itérateur. L'itérateur sera laissé épuisé: sa méthode hasNext () retournera false." Cela signifie que vous ne pouvez plus utiliser l'itérateur par la suite. Lists.newArrayList(some_iterator);peut aider.
En utilisant la bibliothèque Goyave , une autre option est de convertir l' Iterableun List.
List list =Lists.newArrayList(some_iterator);int count = list.size();
Utilisez ceci si vous devez également accéder aux éléments de l'itérateur après avoir obtenu sa taille. En utilisant, Iterators.size()vous ne pouvez plus accéder aux éléments itérés.
@LoveToCode Moins efficace que l'exemple sur la question d'origine
Hiver
2
Bien sûr, la création d'un nouvel objet avec tous les éléments est plus lente que la simple itération et la suppression. À mon humble avis, cette solution est une ligne unique qui améliore la lisibilité du code. Je l'utilise beaucoup pour les collections avec peu d'éléments (jusqu'à 1000) ou lorsque la vitesse n'est pas un problème.
tashuhka
7
Si tout ce que vous avez est l'itérateur, alors non, il n'y a pas de «meilleur» moyen. Si l'itérateur provient d'une collection, vous pourriez aussi bien la taille.
Gardez à l'esprit qu'Iterator est juste une interface pour parcourir des valeurs distinctes, vous auriez très bien un code comme celui-ci
newIterator<Long>(){finalRandom r =newRandom();@Overridepublicboolean hasNext(){returntrue;}@OverridepublicLong next(){return r.nextLong();}@Overridepublicvoid remove(){thrownewIllegalArgumentException("Not implemented");}};
ou
newIterator<BigInteger>(){BigInteger next =BigInteger.ZERO;@Overridepublicboolean hasNext(){returntrue;}@OverridepublicBigInteger next(){BigInteger current = next;
next = next.add(BigInteger.ONE);return current;}@Overridepublicvoid remove(){thrownewIllegalArgumentException("Not implemented");}};
Il n'y a pas de moyen plus efficace, si vous ne disposez que de l'itérateur. Et si l'itérateur ne peut être utilisé qu'une seule fois, alors obtenir le décompte avant d'obtenir le contenu de l'itérateur est ... problématique.
La solution consiste soit à modifier votre application pour qu'elle n'ait pas besoin du décompte, soit à obtenir le décompte par d'autres moyens. (Par exemple, passez un Collectionplutôt que Iterator...)
L'objet iterator contient le même nombre d'éléments que votre collection contenait.
List<E> a =...;Iterator<E> i = a.iterator();int size = a.size();//Because iterators size is equal to list a's size.
Mais au lieu d'obtenir la taille de l'itérateur et d'itérer via l'index 0 à cette taille, il est préférable d'itérer via la méthode next () de l'itérateur.
to provide an implementation-independent method for access, in which the user does not need to know whether the underlying implementation is some form of array or of linked list, and allows the user go through the collection without explicit indexing.
penguin.ewu.edu/~trolfe/LinkedSort/Iterator.htmlRéponses:
Si vous avez juste l'itérateur, c'est ce que vous devrez faire - il ne sait pas combien d'éléments il reste à parcourir, vous ne pouvez donc pas l'interroger pour ce résultat. Il existe des méthodes utilitaires qui semblent faire cela (comme
Iterators.size()
dans Guava), mais en dessous, elles effectuent à peu près la même opération.Cependant, de nombreux itérateurs proviennent de collections, que vous pouvez souvent interroger pour leur taille. Et s'il s'agit d'une classe créée par l'utilisateur pour laquelle vous obtenez l'itérateur, vous pouvez chercher à fournir une méthode size () sur cette classe.
En bref, dans la situation où vous n'avez que l'itérateur, il n'y a pas de meilleur moyen, mais le plus souvent, vous avez accès à la collection ou à l'objet sous-jacent à partir duquel vous pourrez peut-être obtenir directement la taille.
la source
Iterators.size(...)
(mentionné dans d'autres commentaires ci-dessous et dans java-doc): "Renvoie le nombre d'éléments restants dans l'itérateur. L'itérateur sera laissé épuisé: sa méthode hasNext () retournera false." Cela signifie que vous ne pouvez plus utiliser l'itérateur par la suite.Lists.newArrayList(some_iterator);
peut aider.Utilisation de la bibliothèque Guava :
En interne, il itère simplement sur tous les éléments, donc c'est juste pour plus de commodité.
la source
Votre code vous donnera une exception lorsque vous atteindrez la fin de l'itérateur. Vous pourriez faire:
Si vous aviez accès à la collection sous-jacente, vous pourriez appeler
coll.size()
...EDIT OK vous avez modifié ...
la source
Vous devrez toujours itérer. Pourtant, vous pouvez utiliser Java 8, 9 pour faire le comptage sans boucler explicitement:
Voici un test:
Cela imprime:
Assez intéressant, vous pouvez paralléliser l'opération de comptage ici en changeant le
parallel
drapeau sur cet appel:la source
En utilisant la bibliothèque Goyave , une autre option est de convertir l'
Iterable
unList
.Utilisez ceci si vous devez également accéder aux éléments de l'itérateur après avoir obtenu sa taille. En utilisant,
Iterators.size()
vous ne pouvez plus accéder aux éléments itérés.la source
Si tout ce que vous avez est l'itérateur, alors non, il n'y a pas de «meilleur» moyen. Si l'itérateur provient d'une collection, vous pourriez aussi bien la taille.
Gardez à l'esprit qu'Iterator est juste une interface pour parcourir des valeurs distinctes, vous auriez très bien un code comme celui-ci
ou
la source
Il n'y a pas de moyen plus efficace, si vous ne disposez que de l'itérateur. Et si l'itérateur ne peut être utilisé qu'une seule fois, alors obtenir le décompte avant d'obtenir le contenu de l'itérateur est ... problématique.
La solution consiste soit à modifier votre application pour qu'elle n'ait pas besoin du décompte, soit à obtenir le décompte par d'autres moyens. (Par exemple, passez un
Collection
plutôt queIterator
...)la source
pour Java 8, vous pouvez utiliser,
la source
L'objet iterator contient le même nombre d'éléments que votre collection contenait.
Mais au lieu d'obtenir la taille de l'itérateur et d'itérer via l'index 0 à cette taille, il est préférable d'itérer via la méthode next () de l'itérateur.
la source
a
, mais seulementi
?