Question

Je viens d’apprendre comment Java Collections Framework implémente les structures de données dans des listes chaînées. D'après ce que j'ai compris, Iterators sont un moyen de parcourir les éléments d'une structure de données telle qu'une liste. Pourquoi cette interface est-elle utilisée? Pourquoi les méthodes hasNext(), next() et remove() ne sont-elles pas directement codées dans la mise en oeuvre de la structure de données elle-même?

Sur le site Web Java: texte du lien

  

interface publique Iterator < E >

An   itérateur sur une collection. Itérateur   prend la place de l'énumération dans le   Cadre de collections Java. Itérateurs   diffèrent des énumérations de deux manières:

     

  • Les itérateurs permettent à l'appelant de supprimer   éléments du sous-jacent   collection lors de l'itération avec   sémantique bien définie.
  • Noms de méthodes   ont été améliorés.
Cette interface est   un membre des collections Java   Cadre.

J'ai essayé de googler et je n'arrive pas à trouver une réponse définitive. Quelqu'un peut-il nous expliquer pourquoi Sun a choisi de les utiliser? Est-ce à cause d'un meilleur design? Sécurité accrue? Bonnes pratiques d’OO?

Toute aide sera grandement appréciée. Merci.

Était-ce utile?

La solution

  

Pourquoi cette interface est-elle utilisée?

Parce qu'il prend en charge les opérations de base qui permettraient à un programmeur client d'itérer sur tout type de collection (remarque: pas nécessairement un Collection au sens Object).

  

Pourquoi les méthodes ... pas directement   codé à la structure de données   la mise en œuvre elle-même?

Ils le sont, ils sont juste marqués Privé afin que vous ne puissiez pas les atteindre et les jeter. Plus spécifiquement:

  • Vous pouvez implémenter ou sous-classer un Iterator de sorte qu'il fasse quelque chose que ne font pas les standards, sans avoir à modifier l'objet réel sur lequel il itère.
  • Les objets qui peuvent être traversés n'ont pas besoin d'avoir leurs interfaces encombrées de méthodes de parcours, en particulier de méthodes hautement spécialisées.
  • Vous pouvez distribuer Iterators quel que soit le nombre de clients que vous souhaitez et chaque client peut naviguer à son rythme et à son rythme.
  • Java <=> du package java.util en particulier lèvera une exception si le stockage qui les sauvegarde est modifié alors que vous avez encore un <=> out. Cette exception vous permet de savoir que le <=> peut maintenant renvoyer des objets non valides.

Pour les programmes simples, rien de tout cela ne semble en valoir la peine. Le type de complexité qui les rend utiles vous apparaîtra rapidement.

Autres conseils

Vous demandez: & "; Pourquoi les méthodes hasNext (), next () et remove () ne sont-elles pas directement codées pour la mise en oeuvre de la structure de données? &";

L'infrastructure Java Collections choisit de définir l'interface Iterator comme étant externalisée à la collection elle-même. Normalement, chaque collection Java implémentant l'interface Iterable, un programme Java appelle iterator pour créer son propre itérateur afin qu'il puisse être utilisé en boucle. Comme d'autres l'ont déjà souligné, Java 5 nous permet de diriger l'utilisation de l'itérateur, avec une boucle pour chaque objet.

L’externalisation de l’itérateur dans sa collection permet au client de contrôler la manière dont on itère dans une collection. Cela peut être utile, par exemple, dans les cas où il existe une collection illimitée, telle que toutes les pages Web sur Internet à indexer.

Dans le livre GoF classique, le contraste entre les itérateurs internes et externes est clairement défini.

  

Un problème fondamental consiste à décider quelle partie contrôle l’itération, l’itérateur ou le client qui utilise l’itérateur. Lorsque le client contrôle l'itération, l'itérateur est appelé un itérateur externe et, lorsque l'itérateur le contrôle, il est un itérateur interne. Les clients qui utilisent un itérateur externe doivent avancer la traversée et demander explicitement le prochain élément à l'itérateur. En revanche, le client confie à un itérateur interne une opération à exécuter et l’itérateur applique cette opération à chaque élément ....

     

Les itérateurs externes sont plus flexibles que les itérateurs internes. Il est facile de comparer deux collections pour l’égalité avec un itérateur externe, par exemple, mais c’est pratiquement impossible avec les itérateurs internes ... Mais d’un autre côté, les itérateurs internes sont plus faciles à utiliser car ils définissent la logique d’itération pour vous.

Pour un exemple du fonctionnement des itérateurs internes, voir l’API Enumerable de Ruby, qui comporte des méthodes d’itération internes telles que each. En Ruby, l’idée est de passer un bloc de code (c’est-à-dire une fermeture) à un itérateur interne afin qu’une collection puisse s’occuper de sa propre itération.

il est important de garder la collection à l’écart du pointeur. L'itérateur pointe vers un emplacement spécifique dans une collection et ne fait donc pas partie intégrante de la collection. De cette façon, vous pouvez par exemple utiliser plusieurs itérateurs sur la même collection.

l’inconvénient de cette séparation est que l’itérateur n’est pas au courant des modifications apportées à la collection sur laquelle il itère. vous ne pouvez donc pas modifier la structure de la collection et attendre que l'itérateur poursuive son travail sans " plaintes ".

.

L’utilisation de l’interface Iterator permet à toute classe qui implémente ses méthodes d’agir en tant qu’itérateurs. La notion d’interface en Java est en quelque sorte l’obligation contractuelle de fournir certaines fonctionnalités dans une classe qui implements interface, agisse de la manière requise par l’interface. Étant donné que les obligations contractuelles doivent être respectées pour être une classe valide, les autres classes qui voient la classe hasNext(), next(), remove() l'interface et sont ainsi rassurées de savoir que la classe disposera de certaines fonctionnalités.

Dans cet exemple, plutôt que d'implémenter les méthodes (LinkedList) dans la classe hasNext() elle-même, la classe ReversibleLinkedList déclarera qu'elle ReverseIterator est l'interface previous(), afin que les autres utilisateurs sachent que la <= > peut être utilisé comme un itérateur. À son tour, la classe <=> implémentera les méthodes à partir de l'interface <=> (telle que <=>), de sorte qu'elle puisse fonctionner comme un itérateur.

En d’autres termes, la mise en oeuvre d’une interface est une notion de programmation orientée objet permettant de faire savoir aux autres qu’une classe a ce qu’il faut pour être ce qu’elle prétend être.

Cette notion est appliquée en ayant des méthodes qui doivent être implémentées par une classe qui implémente l'interface. Cela permet de s’assurer que les autres classes souhaitant utiliser la classe qui implémente l’interface <=> auront effectivement les méthodes que les itérateurs devraient avoir, telles que <=>.

En outre, il convient de noter que, Java ne disposant pas d'un héritage multiple, l'interface peut être utilisée pour émuler cette fonctionnalité. En mettant en œuvre plusieurs interfaces, on peut avoir une classe qui est une sous-classe pour hériter de certaines fonctionnalités, mais aussi & "; Hériter de &"; les fonctionnalités d'un autre en implémentant une interface. Un exemple serait, si je voulais avoir une sous-classe de la <=> classe appelée <=> qui pourrait itérer dans l'ordre inverse, je pourrais créer une interface appelée <=> et faire en sorte qu'elle fournisse une méthode <=>. Étant donné que <=> implémente déjà <=>, la nouvelle liste réversible aurait implémenté les interfaces <=> et <=>.

Pour en savoir plus sur les interfaces, consultez Qu'est-ce qu'une interface? du didacticiel Java de Sun.

Plusieurs instances d'un interator peuvent être utilisées simultanément. Adressez-les en tant que curseurs locaux pour les données sous-jacentes.

BTW: favoriser les interfaces par rapport aux implémentations concrètes perd le couplage

Recherchez le modèle de conception de l'itérateur, et ici: http://en.wikipedia.org/wiki / Iterator

Parce que vous êtes peut-être en train d’itérer quelque chose qui n’est pas une structure de données. Disons que j'ai une application en réseau qui extrait les résultats d'un serveur. Je peux retourner un wrapper Iterator autour de ces résultats et les diffuser à travers tout code standard acceptant un objet Iterator.

Considérez-le comme un élément clé d’un bon design MVC. Les données doivent aller du modèle (c'est-à-dire la structure de données) à la vue d'une manière ou d'une autre. L'utilisation d'un itérateur comme intermédiaire garantit que la mise en œuvre du modèle n'est jamais exposée. Vous pourriez garder une liste liée en mémoire, extraire des informations d'un algorithme de déchiffrement ou encapsuler des appels JDBC. Cela n’a simplement aucune importance pour la vue, car celle-ci ne concerne que l’interface Iterator.

Un article intéressant sur les avantages et les inconvénients de l'utilisation des itérateurs:

http://www.sei.cmu.edu /pacc/CBSE5/Sridhar-cbse5-final.pdf

Je pense que c'est juste une bonne pratique OO. Vous pouvez avoir un code qui traite toutes sortes d'itérateurs, et vous donne même la possibilité de créer vos propres structures de données ou simplement des classes génériques qui implémentent l'interface itérateur. Vous n'avez pas à vous soucier du type d'implémentation qui se cache derrière.

Juste en M2C, si vous ne le saviez pas: vous pouvez éviter d’utiliser directement l’interface itérateur dans les situations où pour chaque boucle suffira.

En définitive, Iterator capture une abstraction de contrôle applicable à un grand nombre de structures de données. Si vous êtes au courant de votre théorie des catégories, vous pouvez vous laisser impressionner par cet article: L’essence du motif Iterator .

Eh bien, il semble que la première puce permette aux applications multithread (ou mono-thread si vous échouez) de ne pas avoir besoin de verrouiller la collection pour les violations de concurrence. Par exemple, dans .NET, vous ne pouvez pas énumérer et modifier une collection (ou une liste, ni aucun IEnumerable) en même temps sans verrouiller ou hériter de IEnumerable et de méthodes surchargées (nous obtenons des exceptions).

Iterator ajoute simplement une manière courante de parcourir une collection d’articles. Une des fonctionnalités intéressantes est le i.remove () dans lequel vous pouvez supprimer des éléments de la liste sur laquelle vous effectuez une itération. Si vous essayez simplement de supprimer des éléments d’une liste, vous obtiendrez des effets étranges, voire une exception.

L’interface est comme un contrat pour tout ce qui la met en œuvre. Vous dites fondamentalement… tout ce qui implémente un itérateur est garanti d'avoir ces méthodes qui se comportent de la même manière. Vous pouvez également l'utiliser pour passer des types d'itérateurs si c'est tout ce qui compte dans votre code. (vous vous souciez peut-être de quel type de liste il s'agit .. vous voulez juste passer un Iterator) Vous pouvez mettre toutes ces méthodes indépendamment dans les collections, mais vous ne garantissez pas qu'elles se comportent de la même manière ou qu'elles portent même le même nom. signatures.

Les itérateurs sont l’un des nombreux modèles disponibles en Java. Les modèles de conception peuvent être considérés comme des blocs de construction, des styles et une utilisation pratiques de votre code / structure.

Pour en savoir plus sur le modèle de conception d'Iterator, consultez le site Web qui traite d'Iterator ainsi que de nombreux autres modèles de conception. Voici un extrait du site sur Iterator: http://www.patterndepot.com/ put / 8 / Behavioral.html

  

L'Iterator est l'un des plus simples   et le plus fréquemment utilisé de la conception   modèles. Le motif Iterator permet   vous déplacer dans une liste ou   collecte de données à l'aide d'un standard   interface sans avoir à connaître le   détails de l'interne   représentations de ces données. Dans   outre, vous pouvez également définir spéciale   itérateurs qui effectuent une spéciale   traitement et retour uniquement spécifié   éléments de la collecte de données.

Les itérateurs peuvent être utilisés contre tout type de collection. Ils vous permettent de définir un algorithme par rapport à une collection d'éléments, quelle que soit l'implémentation sous-jacente. Cela signifie que vous pouvez traiter une liste, un ensemble, une chaîne, un fichier, un tableau, etc.

Dans dix ans, vous pourrez modifier l’implémentation de votre liste pour une meilleure implémentation et l’algorithme fonctionnera toujours de manière transparente.

Iterator est utile lorsque vous traitez avec Collections en Java.

Utilisez à la pièce (Java1.5) pour parcourir une collection, un tableau ou une liste.

L’interface java.util.Iterator est utilisée dans Java Collections Framework pour permettre la modification de la collection tout en itérant. Si vous souhaitez simplement effectuer une itération propre sur une collection entière, utilisez plutôt for-each, mais le côté positif d'Iterators est la fonctionnalité que vous obtenez: une opération optionnelle remove (), et encore mieux pour l'interface List Iterator, qui offre Les opérations () et set () aussi. Ces deux interfaces vous permettent d'itérer sur une collection et de la modifier structurellement en même temps. Essayer de modifier une collection en la parcourant avec une for, lève une exception ConcurrentModificationException, généralement parce que la collection est modifiée de manière inattendue!

Jetez un coup d'œil à la classe ArrayList

Il a 2 classes privées à l'intérieur (classes internes) appelé Itr et ListItr

Ils implémentent respectivement les interfaces Iterator et ListIterator

classe publique ArrayList ..... {// classe englobante

  private class Itr implements Iterator<E> {

        public E next() {
            return ArrayList.this.get(index++); //rough, not exact
        }

        //we have to use ArrayList.this.get() so the compiler will
        //know that we are referring to the methods in the 
        //enclosing ArrayList class

        public void remove() {
            ArrayList.this.remove(prevIndex);
        }

        //checks for...co mod of the list
        final void checkForComodification() {  //ListItr gets this method as well
             if (ArrayList.this.modCount != expectedModCount) { 
                 throw new ConcurrentModificationException();
             }
        }
  }

  private class ListItr extends Itr implements ListIterator<E> {
         //methods inherted....
        public void add(E e) {
            ArrayList.this.add(cursor, e);
        }

        public void set(E e) {
            ArrayList.this.set(cursor, e);
        }
  }

}

Lorsque vous appelez les méthodes iterator () et listIterator (), elles renvoient une nouvelle instance de la classe privée Itr ou ListItr, et puisque ces classes internes sont & "dans &"; classe ArrayList englobante, ils peuvent modifier librement ArrayList sans déclencher une exception ConcurrentModificationException, sauf si vous modifiez la liste en même temps (de manière concurrente) via les méthodes set () add () ou remove () de la classe ArrayList.

scroll top