Pouvons-nous écrire notre propre itérateur en Java?
104
Si j'ai une liste contenant [alice, bob, abigail, charlie]et que je veux écrire un itérateur tel qu'il itère sur des éléments commençant par «a», puis-je écrire le mien? Comment puis je faire ça ?
Sûr. Un itérateur n'est qu'une implémentation de l' java.util.Iteratorinterface. Si vous utilisez un objet itérable existant (par exemple, a LinkedList) de java.util, vous devrez soit le sous-classer et remplacer sa iteratorfonction afin de renvoyer la vôtre, soit fournir un moyen d'encapsuler un itérateur standard dans votre Iteratorinstance spéciale (qui a l'avantage d'être plus largement utilisé), etc.
bonne réponse .... +1 Cependant, vous n'êtes pas obligé de sous-classer LinkedList. Vous pouvez écrire un CustomIterator instancié avec le nouveau CustomIterator (somelist), car les interfaces ne disent rien sur les constructeurs.
gd1
1
@Giacomo: C'est ce que je voulais dire par "... ou fournir un moyen d'encapsuler un itérateur standard dans votre Iteratorinstance spéciale ..." (et merci). :-)
TJ Crowder
196
La meilleure option réutilisable est d'implémenter l'interface Iterable et de remplacer la méthode iterator ().
Voici un exemple d'une classe de type ArrayList implémentant l'interface, dans laquelle vous remplacez la méthode Iterator ().
Cette classe implémente l'interface Iterable à l'aide de Generics . Considérant que vous avez des éléments dans le tableau, vous pourrez obtenir une instance d'un Iterator, qui est l'instance nécessaire utilisée par la boucle "foreach", par exemple.
Vous pouvez simplement créer une instance anonyme de l'itérateur sans créer d'étendre Iterator et profiter de la valeur de currentSize pour vérifier jusqu'à l'endroit où vous pouvez naviguer sur le tableau (disons que vous avez créé un tableau d'une capacité de 10, mais vous n'en avez que 2 éléments à 0 et 1). L'instance aura son compteur propriétaire de l'endroit où elle se trouve et tout ce que vous avez à faire est de jouer avec hasNext (), qui vérifie si la valeur actuelle n'est pas nulle, et next (), qui renverra l'instance de votre currentIndex. Voici un exemple d'utilisation de cette API ...
publicstaticvoid main(String[] args){// create an array of type IntegerInteger[] numbers =newInteger[]{1,2,3,4,5};// create your list and hold the values.SOList<Integer> stackOverflowList =newSOList<Integer>(numbers);// Since our class SOList is an instance of Iterable, then we can use it on a foreach loopfor(Integer num : stackOverflowList){System.out.print(num);}// creating an array of StringsString[] languages =newString[]{"C","C++","Java","Python","Scala"};// create your list and hold the values using the same list implementation.SOList<String> languagesList =newSOList<String>(languages);System.out.println("");// Since our class SOList is an instance of Iterable, then we can use it on a foreach loopfor(String lang : languagesList){System.out.println(lang);}}// will print "12345//C//C++//Java//Python//Scala
Si vous le souhaitez, vous pouvez également le parcourir en utilisant l'instance Iterator:
// navigating the iteratorwhile(allNumbers.hasNext()){Integer value = allNumbers.next();if(allNumbers.hasNext()){System.out.print(value +", ");}else{System.out.print(value);}}// will print 1, 2, 3, 4, 5
Maintenant, pour obtenir les effets de ce dont vous avez besoin, je pense que vous devez brancher un concept de filtre dans l'itérateur ... Puisque l'itérateur dépend des valeurs suivantes, il serait difficile de retourner true sur hasNext (), puis filtre l'implémentation next () avec une valeur qui ne commence pas par un caractère "a" par exemple. Je pense que vous devez jouer avec un Interator secondaire basé sur une liste filtrée avec les valeurs avec le filtre donné.
30 autres personnes ne pensaient pas que c'était un jeu de mots :)
Marcello de Sales
2
C'est une bonne pratique de lever une exception d'opération non prise en charge à partir de nos méthodes implémentées. Je pense que c'est une bonne idée de lancer une exception d'opération non prise en charge de la méthode remove ()!
darshan
2
Désolé @darshan, mais cette solution concerne "comment écrire des itérateurs" ... Si l'objectif était "d'écrire du code parfaitement écrit", ce serait là!
Marcello de Sales
pas clair pourquoi la vérification 'arrayList [currentIndex]! = null' est requise dans hasNext (). quelqu'un peut-il expliquer s'il vous plaît.
Bhushan Karmarkar
12
Bon exemple pour Iterable pour calculer factoriel
FactorialIterable fi =newFactorialIterable(10);Iterator<Integer> iterator = fi.iterator();while(iterator.hasNext()){System.out.println(iterator.next());}
Vous pouvez implémenter votre propre Iterator. Votre itérateur peut être construit pour encapsuler l'itérateur retourné par la liste, ou vous pouvez garder un curseur et utiliser la méthode get (int index) de la liste. Il vous suffit d'ajouter une logique à la méthode suivante de votre Iterator ET à la méthode hasNext pour prendre en compte vos critères de filtrage. Vous devrez également décider si votre itérateur prendra en charge l'opération de suppression.
ListIterator est l'itérateur du tableau qui renvoie les éléments commençant par «a».
Il n'est pas nécessaire d'implémenter une interface Iterable. Mais c'est une possibilité.
Il n'est pas nécessaire de l'implémenter de manière générique.
Il satisfait pleinement le contrat pour hasNext () et next (). c'est-à-dire que si hasNext () dit qu'il y a encore des éléments, next () retournera ces éléments. Et si hasNext () ne dit plus d'éléments, il renvoie une NoSuchElementExceptionexception valide .
Réponses:
Sûr. Un itérateur n'est qu'une implémentation de l'
java.util.Iterator
interface. Si vous utilisez un objet itérable existant (par exemple, aLinkedList
) dejava.util
, vous devrez soit le sous-classer et remplacer saiterator
fonction afin de renvoyer la vôtre, soit fournir un moyen d'encapsuler un itérateur standard dans votreIterator
instance spéciale (qui a l'avantage d'être plus largement utilisé), etc.la source
Iterator
instance spéciale ..." (et merci). :-)La meilleure option réutilisable est d'implémenter l'interface Iterable et de remplacer la méthode iterator ().
Voici un exemple d'une classe de type ArrayList implémentant l'interface, dans laquelle vous remplacez la méthode Iterator ().
Cette classe implémente l'interface Iterable à l'aide de Generics . Considérant que vous avez des éléments dans le tableau, vous pourrez obtenir une instance d'un Iterator, qui est l'instance nécessaire utilisée par la boucle "foreach", par exemple.
Vous pouvez simplement créer une instance anonyme de l'itérateur sans créer d'étendre Iterator et profiter de la valeur de currentSize pour vérifier jusqu'à l'endroit où vous pouvez naviguer sur le tableau (disons que vous avez créé un tableau d'une capacité de 10, mais vous n'en avez que 2 éléments à 0 et 1). L'instance aura son compteur propriétaire de l'endroit où elle se trouve et tout ce que vous avez à faire est de jouer avec hasNext (), qui vérifie si la valeur actuelle n'est pas nulle, et next (), qui renverra l'instance de votre currentIndex. Voici un exemple d'utilisation de cette API ...
Si vous le souhaitez, vous pouvez également le parcourir en utilisant l'instance Iterator:
La documentation foreach se trouve à l' adresse http://download.oracle.com/javase/1,5.0/docs/guide/language/foreach.html . Vous pouvez jeter un oeil à une mise en œuvre plus complète à mon code google pratique personnelle .
Maintenant, pour obtenir les effets de ce dont vous avez besoin, je pense que vous devez brancher un concept de filtre dans l'itérateur ... Puisque l'itérateur dépend des valeurs suivantes, il serait difficile de retourner true sur hasNext (), puis filtre l'implémentation next () avec une valeur qui ne commence pas par un caractère "a" par exemple. Je pense que vous devez jouer avec un Interator secondaire basé sur une liste filtrée avec les valeurs avec le filtre donné.
la source
for instance
, est-ce un jeu de mots?Bon exemple pour Iterable pour calculer factoriel
Code court pour Java 1.8
Classe Iterable personnalisée
Classe Iterator personnalisée
la source
Voici le code complet pour écrire un itérateur tel qu'il itère sur les éléments qui commencent par 'a':
Classe Iterator personnalisée
la source
Vous pouvez implémenter votre propre Iterator. Votre itérateur peut être construit pour encapsuler l'itérateur retourné par la liste, ou vous pouvez garder un curseur et utiliser la méthode get (int index) de la liste. Il vous suffit d'ajouter une logique à la méthode suivante de votre Iterator ET à la méthode hasNext pour prendre en compte vos critères de filtrage. Vous devrez également décider si votre itérateur prendra en charge l'opération de suppression.
la source
Voici la réponse complète à la question.
ListIterator
est l'itérateur du tableau qui renvoie les éléments commençant par «a».NoSuchElementException
exception valide .la source