Introduction détaillée à Iterable et Iterator en Java
Cet article vous apporte une introduction détaillée à Iterable et Iterator en Java. Il a une certaine valeur de référence. Les amis dans le besoin peuvent s'y référer.
En Java, nous pouvons parcourir la collection List des manières suivantes :
List<Integer> list = new ArrayList<>(); list.add(5); list.add(23); list.add(42); for (int i = 0; i < list.size(); i++) { System.out.print(list.get(i) + ","); } Iterator it = list.iterator(); while (it.hasNext()) { System.out.print(it.next() + ","); } for (Integer i : list) { System.out.print(i + ","); }
La première est une boucle for ordinaire, la seconde est une traversée d'itérateur et les Trois sont les pour chaque boucle. Les deux dernières méthodes impliquent des objets itérateurs et itérables en Java. Examinons ensuite les différences entre ces deux objets et comment implémenter une boucle for each dans une classe personnalisée.
Iterator et Iterable
iterator est un objet itérateur en Java, qui est la dépendance sous-jacente qui peut parcourir une collection telle que List. L'interface itérable définit une méthode qui renvoie l'itérateur, ce qui équivaut à encapsuler l'itérateur. En même temps, les classes qui implémentent l'interface itérable peuvent prendre en charge chaque boucle.
Détails internes de l'Iterator
Les principales méthodes de l'interface Iterator dans jdk sont les suivantes :
public interface Iterator<E> { boolean hasNext(); E next(); }
Iterator définit la méthode d'accès itératif à la collection via ce qui précède deux méthodes, et l'implémentation spécifique dépend de différentes classes d'implémentation. La classe de collection spécifique implémente les méthodes dans l'interface Iterator pour implémenter l'itération.
On peut constater que l'interface Iterator n'est pas implémentée dans List, mais que l'interface Iterable est implémentée. Une observation plus approfondie du code source de l'interface Iterable montre qu'elle renvoie simplement un objet Iterator.
public interface Iterable<T> { Iterator<T> iterator(); }
On peut donc utiliser la méthode suivante pour itérer la List (en appelant la méthode iterator())
Iterator it = list.iterator(); while (it.hasNext()) { System.out.print(it.next() + ","); }
En même temps, si vous implémentez l'interface Iterable, vous pouvez également utiliser la boucle for each.
Principe de for each
En fait, la boucle for each s'appuie également sur l'itérateur Iterator, mais le sucre syntaxique fourni par Java, le compilateur Java le convertira en itérateur Iterator pour le parcours . Nous décompilons ce qui suit pour chaque boucle :
for (Integer i : list) { System.out.println(i); }
Après la décompilation :
Integer i; for(Iterator iterator = list.iterator(); iterator.hasNext(); System.out.println(i)){ i = (Integer)iterator.next(); }
Vous pouvez voir que Java pour chaque boucle améliorée est implémenté via l'itérateur.
Discussion approfondie de la relation entre Iterable et Iterator
J'ai une question, pourquoi ne pas simplement mettre les méthodes hasNext() et next() directement dans l'interface Iterable et d'autres classes peut-on les mettre en œuvre directement ?
La raison est que certaines classes de collection peuvent avoir plus d'une méthode de parcours. Une classe qui implémente Iterable peut implémenter plusieurs classes internes Iterator, telles que les deux classes internes LinkedList
et ListItr
dans DescendingIterator
. Le parcours bidirectionnel et le parcours inverse sont implémentés respectivement. Implémentez différentes méthodes de parcours en renvoyant différents Iterator
, ce qui est plus flexible. Si vous fusionnez les deux interfaces, vous ne pouvez pas renvoyer des classes d'implémentation Iterator
différentes. Le code source pertinent de ListItr est le suivant :
public ListIterator<E> listIterator(int index) { checkPositionIndex(index); return new ListItr(index); } private class ListItr implements ListIterator<E> { ... ListItr(int index) { // assert isPositionIndex(index); next = (index == size) ? null : node(index); nextIndex = index; } public boolean hasNext() { return nextIndex < size; } ...
Comme indiqué ci-dessus, l'itérateur peut être renvoyé en appelant la méthode list.listIterator()
(list.iterator()
n'est que son implémentation par défaut)
DescendingIterator
Le code source est le suivant :
public Iterator<E> descendingIterator() { return new DescendingIterator(); } private class DescendingIterator implements Iterator<E> { private final ListItr itr = new ListItr(size()); public boolean hasNext() { return itr.hasPrevious(); } public E next() { return itr.previous(); } public void remove() { itr.remove(); } }
Cet itérateur peut également être utilisé via list.descendingIterator()
.
Implémentez votre propre itérateur
Nous avons maintenant une classe personnalisée ArrayMap, maintenant si nous la parcourons pour chacun comme suit :
ArrayMap<String, Integer> am = new ArrayMap<>(); am.put("hello", 5); am.put("syrups", 10); for (String s: am) { System.out.println(s); }
Puisque nous ne l'avons pas implémenté hashNext et ensuite les méthodes abstraites, elles ne peuvent donc pas être parcourues.
Classe d'itérateur personnalisée
Nous personnalisons d'abord une classe d'itérateur pour implémenter les méthodes hashNext et next, et l'utilisons comme classe interne d'ArrayMap. Le code pertinent est le suivant :
<🎜. >public class KeyIterator implements Iterator<K> { private int ptr; public KeyIterator() { ptr = 0; } @Override public boolean hasNext() { return (ptr != size); } @Override public K next() { K returnItem = keys[ptr]; ptr += 1; return returnItem; } }
ArrayMap<String, Integer> am = new ArrayMap<>(); am.put("hello", 5); am.put("syrups", 10); ArrayMap.KeyIterator ami = am.new KeyIterator(); while (ami.hasNext()) { System.out.println(ami.next()); }
public class ArrayMap<K, V> implements Iterable<K> { private K[] keys; private V[] values; int size; public ArrayMap() { keys = (K[]) new Object[100]; values = (V[]) new Object[100]; size = 0; } .... }
@Override public Iterator<K> iterator() { return new KeyIterator(); }
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Outils d'IA chauds

Undresser.AI Undress
Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover
Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool
Images de déshabillage gratuites

Clothoff.io
Dissolvant de vêtements AI

AI Hentai Generator
Générez AI Hentai gratuitement.

Article chaud

Outils chauds

Bloc-notes++7.3.1
Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise
Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1
Puissant environnement de développement intégré PHP

Dreamweaver CS6
Outils de développement Web visuel

SublimeText3 version Mac
Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Guide de la racine carrée en Java. Nous discutons ici du fonctionnement de Square Root en Java avec un exemple et son implémentation de code respectivement.

Guide du nombre parfait en Java. Nous discutons ici de la définition, comment vérifier le nombre parfait en Java ?, des exemples d'implémentation de code.

Guide du générateur de nombres aléatoires en Java. Nous discutons ici des fonctions en Java avec des exemples et de deux générateurs différents avec d'autres exemples.

Guide de Weka en Java. Nous discutons ici de l'introduction, de la façon d'utiliser Weka Java, du type de plate-forme et des avantages avec des exemples.

Guide du nombre de Smith en Java. Nous discutons ici de la définition, comment vérifier le numéro Smith en Java ? exemple avec implémentation de code.

Dans cet article, nous avons conservé les questions d'entretien Java Spring les plus posées avec leurs réponses détaillées. Pour que vous puissiez réussir l'interview.

Java 8 présente l'API Stream, fournissant un moyen puissant et expressif de traiter les collections de données. Cependant, une question courante lors de l'utilisation du flux est: comment se casser ou revenir d'une opération FOREAK? Les boucles traditionnelles permettent une interruption ou un retour précoce, mais la méthode Foreach de Stream ne prend pas directement en charge cette méthode. Cet article expliquera les raisons et explorera des méthodes alternatives pour la mise en œuvre de terminaison prématurée dans les systèmes de traitement de flux. Lire plus approfondie: Améliorations de l'API Java Stream Comprendre le flux Forach La méthode foreach est une opération terminale qui effectue une opération sur chaque élément du flux. Son intention de conception est

Guide de TimeStamp to Date en Java. Ici, nous discutons également de l'introduction et de la façon de convertir l'horodatage en date en Java avec des exemples.
