Question

Je suis en train de comprendre les interfaces Java Iterator et Iterable

Je suis en train d'écrire cette classe

class MyClass implements Iterable<String> {
    public String[] a = null;
    public MyClass(String[] arr) {
        a = arr;    
    }

    public MyClassIterator iterator() {
        return new MyClassIterator(this);
    }

    public class MyClassIterator implements Iterator<String> {
        private MyClass myclass = null;
        private int count = 0;
        public MyClassIterator(MyClass m) {
            myclass = m;    
        }

        public boolean hasNext() {
            return count < myclass.a.length;
        }
        public String next() {
            int t = count;
            count++;
            return myclass.a[t];
        }

        public void remove() {
            throw new UnsupportedOperationException();
        }
    }   
}

Il semble fonctionner.

que je devrais faire:

Myclass implements Iterable<Stirng>, Iterator<String> {

}

Ou devrais-je mettre MyClassIterator en dehors MyClass comme

class MyClass implements Iterable<String> {
    public String[] a = null;
    public MyClass(String[] arr) {
        a = arr;    
    }
    public MyClassIterator iterator() {
        return new MyClassIterator(this);
    }
}


    public class MyClassIterator implements Iterator<String> {
        private MyClass myclass = null;
        private int count = 0;
        public MyClassIterator(MyClass m) {
            myclass = m;    
        }

        public boolean hasNext() {
            return count < myclass.a.length;
        }
        public String next() {
            int t = count;
            count++;
            return myclass.a[t];
        }

        public void remove() {
            throw new UnsupportedOperationException();
        }
    }   

Quelle est la meilleure?

Était-ce utile?

La solution

Vous devriez presque jamais mettre en œuvre à la fois Iterable et Iterator dans la même classe. Ils font des choses différentes. Itérateur est naturellement stateful - comme vous itérer l'utiliser, il doit mettre à jour sa vision du monde. Un itératives, cependant, ne doit être en mesure de créer de nouveaux itérateurs. En particulier, vous pourriez avoir plusieurs itérateurs travaillant sur le même original itérables en même temps.

Votre approche actuelle est à peu près correct -. Il y a des aspects de la mise en œuvre que je changerais, mais il va bien en termes de la séparation des responsabilités

Autres conseils

Vous étiez sur la bonne voie avec votre premier essai. MyClass n'a besoin que de mettre en œuvre Iterable<String>, ce qui vous oblige à fournir une implémentation de Iterator<String> revenir de Iterable<String>.iterator().

Il n'y a pas besoin de mettre à l'extérieur de MyClassIterator de MyClass parce que dans la plupart des cas, vous ne même pas besoin d'utiliser directement le Iterator<String> (il est utilisé implicitement par la syntaxe for .. in .. sur Iterable<String>s), et dans tous les autres cas, l'interface est suffisante, à moins que vous en fait ajouter un comportement supplémentaire à la mise en œuvre (que vous aurez probablement jamais besoin de faire).

Voici comment je le ferais, voir les commentaires inline:

import java.util.Iterator;

class MyClass implements Iterable<String>{
    public String[] a=null; //make this final if you can
    public MyClass(String[] arr){
        a=arr; //maybe you should copy this array, for fear of external modification
    }

    //the interface is sufficient here, the outside world doesn't need to know
    //about your concrete implementation.
    public Iterator<String> iterator(){
        //no point implementing a whole class for something only used once
        return new Iterator<String>() {
            private int count=0;
            //no need to have constructor which takes MyClass, (non-static) inner class has access to instance members
            public boolean hasNext(){
                //simplify
                return count < a.length;
            }
            public String next(){
                return a[count++]; //getting clever
            }

            public void remove(){
                throw new UnsupportedOperationException();
            }
        };
    }
}

Vous ne devriez pas faire Myclass implements Iterable<String>,Iterator<String>{ depuis itérateurs sont à usage unique. À l'exception des itérateurs de la liste, il n'y a aucun moyen de les retourner au début.

Par ailleurs, vous pouvez sauter la

MyClass myClass;
public MyClassInterator(MyClass m){
  myclass=m;  
}

et au lieu de référencer

myClass

référence

MyClass.this

Votre classe interne n'est pas statique, MyClass.this fera référence à l'instance de la classe de fermeture qui l'a créé.

Je suppose que c'est un moyen standard pour mettre en œuvre le Iterable et Iterator en même temps.

// return list of neighbors of v
public Iterable<Integer> adj(int v) {
    return new AdjIterator(v);
}

// support iteration over graph vertices
private class AdjIterator implements Iterator<Integer>, Iterable<Integer> {
    private int v;
    private int w = 0;

    AdjIterator(int v) {
        this.v = v;
    }

    public Iterator<Integer> iterator() {
        return this;
    }

    public boolean hasNext() {
        while (w < V) {
            if (adj[v][w]) return true;
            w++;
        }
        return false;
    }

    public Integer next() {
        if (!hasNext()) {
            throw new NoSuchElementException();
        }
        return w++;
    }

Référence https://algs4.cs.princeton.edu/41graph/ AdjMatrixGraph.java.html .

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top