在同一个类中实现Java Iterator和Iterable?

时间:2011-04-29 18:56:20

标签: java iterator iterable

我正在尝试理解Java IteratorIterable接口

我正在写这门课

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> {

}

或者我应该将MyClassIterator放在MyClass之外作为

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

哪一个更好?

4 个答案:

答案 0 :(得分:33)

您几乎永远不会在同一个班级同时实施IterableIterator。他们做不同的事情。迭代器自然是有状态的 - 当你使用它迭代时,它必须更新它的世界观。但是,迭代只需要能够创建新的迭代器。特别是,你可以让几个迭代器同时在同一个原始迭代上工作。

你目前的做法非常好 - 我会改变实施的各个方面,但在责任分离方面却很好。

答案 1 :(得分:7)

你第一次尝试就走上了正轨。 MyClass只需要实施Iterable<String>,这反过来要求您提供从Iterator<String>返回的Iterable<String>.iterator()实施。

没有必要将MyClassIterator放在MyClass之外,因为在大多数情况下,您甚至不需要直接使用Iterator<String>for .. in ..隐式使用Iterable<String> 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(); } }; } } s)上的语法,在所有其他情况下,除非您实际向实现添加其他行为(您可能不需要这样做),否则接口就足够了。

以下是我的方法,请参阅内联评论:

{{1}}

答案 2 :(得分:2)

您不应该Myclass implements Iterable<String>,Iterator<String>{,因为迭代器是一次性使用的。除了列表迭代器之外,没有办法将它们返回到开头。

顺便提一下,您可以跳过

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

而不是引用

myClass

参考

MyClass.this

您的内部类不是静态的,因此MyClass.this将引用创建它的封闭类的实例。

答案 3 :(得分:0)

我认为这是同时实现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