web-dev-qa-db-ja.com

Java IteratorとIterableを同じクラスに実装しますか?

Java IteratorおよびIterableインターフェースを理解しようとしています

私はこのクラスを書いています

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();
        }
    }   
}

動作しているようです。

私が持っている必要があります:

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

}

または、MyClassIteratorMyClassの外に置く必要があります

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();
        }
    }   

どちらがいいですか?

15
icn

ほぼ決してIterableIteratorの両方を同じクラスに実装する必要があります。彼らは異なることをします。イテレータは当然ステートフル-使用を繰り返すと、世界観を更新する必要があります。ただし、イテレータは、新しいイテレータを作成できる必要があるだけです。特に、複数のイテレータを同じ元のイテレータで同時に動作させることができます。

あなたの現在のアプローチはほとんど問題ありません-私が変更したい実装の側面がありますが、責任の分離という点では問題ありません。

33
Jon Skeet

あなたは最初の試みで順調に進んでいました。 MyClassは_Iterable<String>_を実装するだけでよく、Iterable<String>.iterator()から戻るには_Iterator<String>_実装を提供する必要があります。

MyClassIteratorMyClassの外に置く必要はありません。ほとんどの場合、_Iterator<String>_を直接使用する必要はないからです(_for .. in .._構文によって暗黙的に使用されます)。 _Iterable<String>_ s)で、他のすべての場合、実装に実際に追加の動作を追加しない限り、インターフェイスで十分です(これはおそらく行う必要はありません)。

これが私がそれをする方法です、インライン化されたコメントを見てください:

_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();
            }
        };
    }
}
_
7
Stephen Swensen

イテレータはシングルユースであるため、Myclass implements Iterable<String>,Iterator<String>{を実行しないでください。リストイテレータを除いて、それらを最初に戻す方法はありません。

ちなみに、スキップすることができます

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

参照する代わりに

myClass

参照

MyClass.this

内部クラスは静的ではないため、MyClass.thisはそれを作成した囲んでいるクラスのインスタンスを参照します。

2
Mike Samuel

これは、IterableとIteratorを同時に実装するための標準的な方法だと思います。

// 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++;
    }

参照 https://algs4.cs.princeton.edu/41graph/AdjMatrixGraph.Java.html

0
8cold8hot