2

我的问题是:是否可以仅通过实施来通过容器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
}
4

6 回答 6

4

Iterable和之间存在逻辑差异Iterator

  • 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();
    ....
}
于 2013-06-05T08:49:21.130 回答
4

容器上的两次连续迭代怎么样:

  • 通过直接实现Iterator,由于变量的 Iterator 将由所有客户端共享,因此您将无法多次轻松地遍历您的集合...

  • 通过定义一个方法Iterator:(如 on AbstractList):

    公共迭代器 iterator() { return new Itr(); //每次新实例 }

    为每个时间创建一个新实例,Iterator您可以根据需要对其进行多次迭代。(当然,最好不要同时)。

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

于 2013-06-05T08:53:35.780 回答
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容器中每个可能的对都会被调用。他们会从你的班级看到的行为会让他们头晕目眩。如果生产中的错误被追踪到这个实现,你的队友会......让我们说他们不会欣赏它。

于 2013-06-05T09:09:00.013 回答
3

为了使用enhanced for-loop(又名花哨的 for 循环),您必须实现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或者您希望在它的某些方法中包含一些逻辑,例如lazy loading在方法中,请实现一个迭代器next()

于 2013-06-05T08:46:08.617 回答
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.
    }
}
于 2013-06-05T08:47:33.437 回答
1

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

于 2013-06-05T08:46:10.647 回答