为什么不能循环直接实现Iterator的类?

时间:2013-06-05 08:39:26

标签: java for-loop iterator iterable

我的问题是:是否可以仅通过实施Iterator来浏览容器,即不实施Iterable

是否可以这样做:

//From somewhere
Container c = new Container();
//I add elements to the list in the c object.

for(String s : c){
    //Warning: It is not applicable for this expression...
}


class Container implements Iterator<String>{
    //Here I implement a single linked list

    //Here I implement all of the methods of Iterator
}

6 个答案:

答案 0 :(得分:4)

IterableIterator之间存在逻辑差异。

  • Iterable是可以迭代的集合或数据结构。它是一个数据持有者。

  • Iterator是定义迭代逻辑的对象(以什么方式和顺序循环通过Iterable的元素)。它(并且大多数时候应该)可以与数据结构或集合的逻辑分开。目的是能够为同一Iterator定义多个Iterable实现 我错过重要点,但在其他答案中出现,是保持循环状态远离可迭代对象。这允许同时循环通过相同的集合,因为每个循环将使用单独的迭代器实例。

一个简单的例子是将两个迭代器写入ArrayList,一个循环向前,另一个向后循环。您只需要在现有类(Iterator)上创建ArrayList实现,而无需修改后者。因此,可以只实现一个迭代器。

然而,Java语言中的for循环结构设计用于迭代。代码:

for (Object o : collecton) { 
    ...
}

由编译器翻译为:

Iterator i = collection.iterator();
while (i.hasNext()) {
  ....
}

因此,迭代器本身不能以标准方式使用for循环。或者你可以像这样使用它:

for (Iterator i = collection.iterator(); i.hasNext(); ) {
    Object current = i.next();
    ....
}

答案 1 :(得分:4)

如何在容器上连续两次迭代:

  • 通过直接实现Iterator,由于变量的Iterator将由所有客户共享,因此您将无法在您的集合中多次迭代...

  • 通过定义方法Iterator :(与AbstractList上的方法类似):

    public Iterator iterator(){     return new Itr(); //每次新实例 }

    每次创建Iterator的新实例允许您根据需要迭代多次。 (当然,最好不要同时)。

此外,它避免违反单一责任原则,因为迭代容器的方式代表了另一个目标而不是“定义”容器。

答案 2 :(得分:4)

即使这种设计只是荒谬,只是为了娱乐你的问题,你可以这样写:

public class Container implements Iterable<String>, Iterator<String> {
  @Override public Iterator<String> iterator() { return this; }

  ... everything else you envision for your class ...
}

然后你就可以使用

for (String s : container)

你可以把它写成一个学习经历,但我强烈建议你永远不要在一个真实的项目上尝试。反对它的主要原因是期望iterator方法总是返回一个新的,独立的迭代器,而这个实现实现了相反的结果。举一个具体的例子,假设某人需要自己迭代容器的笛卡尔积:

for (String s1 : container)
  for (String s2 : container) 
     processPair(s1, s2);

每个Java程序员都会告诉您,毫无疑问,processPair将从容器中调用每个可能的对。他们会从你的班级中看到的行为会使他们的头脑旋转。如果生产中的一个错误被追溯到这个实现,那么你的队友会...让我们说他们不会欣赏它。

答案 3 :(得分:3)

要使用enhanced for-loop(a.k.a花式for-loop),您必须实施Iterable而不是Iterator

当然你可以实现Iterator,在这种情况下你的容器将是Iterator

public class Cont<T> implements Iterator<T> {

    @Override
    public boolean hasNext() {
        // TODO implment
        return false;
    }

    @Override
    public T next() {
        // TODO implment
        return null;
    }

    @Override
    public void remove() {
        // TODO implment
    }

}

你可以这样使用它:

public static void main(String... args) {
    Cont cont = new Cont<SomeType>();
    while(cont.hasNext()) {
        SomeType obj = cont.next();
    }
}

通常的情况是Implment Iterable,因此您可以使用所有可用的语言功能。如果要对Collection进行编码,或者希望在其某些方法中包含某些逻辑,请实现Iterator,例如lazy loading方法中的next()

答案 4 :(得分:3)

即使您拥有class implements Iterator<T>才能获得iterator(),您必须实施iterable并返回iterator

public class MyCollection<E> implements Iterable<E>{

    public Iterator<E> iterator() {
        return new MyIterator<E>();
    }
}

以下是MyIterator类的相应实现框架:

public class MyIterator <T> implements Iterator<T> {

    public boolean hasNext() {

        //implement...
    }

    public T next() {
        //implement...;
    }

    public void remove() {
        //implement... if supported.
    }
}

答案 5 :(得分:1)

如果您想使用简单的 for-each 语句 - 。您需要使用Iterator<E>方法从Iterable<E>对象调用iterator()对象。