迭代器和可迭代之间有什么区别,以及如何使用它们?


195

我是Java的新手,我真的对迭代器和可迭代感到困惑。谁能向我解释并举例说明?

Answers:


199

An Iterable是可以迭代的一系列元素的简单表示。它没有任何迭代状态,例如“当前元素”。相反,它具有一种产生的方法Iterator

An Iterator是具有迭代状态的对象。它可以让您检查是否有更多元素使用,hasNext()并使用移至下一个元素(如果有)next()

通常,an Iterable应该能够产生任意数量的有效Iterators。


如果Iterable拥有has interalexternaliterator,或者可能拥有其中任何一个,那会很重要吗?
sakhunzai 2015年

90

的实现Iterable是提供Iterator自身的实现:

public interface Iterable<T>
{
    Iterator<T> iterator();
}

迭代器是一种简单的方法,它允许某些迭代器在没有分配特权的情况下循环访问数据集合(尽管具有删除功能)。

public interface Iterator<E>
{
    boolean hasNext();
    E next();
    void remove();
}

参见Javadoc


16

我将以示例的形式回答有关ArrayList的问题,以帮助您更好地理解..

  1. 可迭代的接口强制其子类实现抽象方法“ iterator()”。
public interface Iterable {
  ...
  abstract Iterator<T> iterator(); //Returns an 'Iterator'(not iterator) over elements of type T.
  ...
}
  1. Iterator接口强制其子类实现抽象方法“ hasNext()”和“ next()”。
public interface Iterator {
  ...
  abstract boolean hasNext(); //Returns true if the iteration has more elements.
  abstract E next();          //Returns the next element in the iteration.
  ...
}
  1. ArrayList实现List,List扩展Collection,Collection扩展Iterable。。也就是说,您会看到类似

    '可迭代<-集合<-列表<-ArrayList'

。Iterable,Collection和List仅声明抽象方法“ iterator()”,而ArrayList单独实现它。

  1. 我将使用以下“ iterator()”方法显示ArrayList源代码,以获取更多详细信息。

“ iterator()”方法返回实现“ Iterator”的类“ Itr”的对象。

public class ArrayList<E> ... implements List<E>, ...
{
  ...
  public Iterator<E> iterator() {
              return new Itr();
  }


  private class Itr implements Iterator<E> {
          ...

          public boolean hasNext() {
              return cursor != size;
          }
          @SuppressWarnings("unchecked")
          public E next() {
              checkForComodification();
              int i = cursor;
              if (i >= size)
                  throw new NoSuchElementException();
              Object[] elementData = ArrayList.this.elementData;
              if (i >= elementData.length)
                  throw new ConcurrentModificationException();
              cursor = i + 1;
              return (E) elementData[lastRet = i];
          }
          ...
  }
}
  1. 其他一些方法或类将通过使用Iterator(Itr)来迭代诸如ArrayList之类的集合的元素。

这是一个简单的例子。

public static void main(String[] args) {

    List<String> list = new ArrayList<>();
    list.add("a");
    list.add("b");
    list.add("c");
    list.add("d");
    list.add("e");
    list.add("f");

    Iterator<String> iterator = list.iterator();
    while (iterator.hasNext()) {
        String string = iterator.next();
        System.out.println(string);
    }
}

现在清楚了吗?:)


好答案。
Kavindu Dodanduwa

我理解了这篇文章,但是如果我想编写一个返回类型是Iterable<T>在这种情况下的方法,那我们需要执行哪些步骤呢?请也建议该示例。
Prasanna Sasne

12

如果一个集合是可迭代的,则可以使用迭代器对其进行迭代(因此可以在每个循环中使用它。)迭代器是将迭代整个集合的实际对象。


2
仅供参考,java.util.Collection始终实现java.util.Iterable。
Paul Draper

2
不是java.lang.Iterable
ulab

这是java.lang.Iterable
aldok,

9

实现Iterable接口允许对象成为“ foreach”语句的目标。

class SomeClass implements Iterable<String> {}

class Main 
{
  public void method()
  {
     SomeClass someClass = new SomeClass();
     .....

    for(String s : someClass) {
     //do something
    }
  }
}

迭代器是一个接口,具有用于迭代元素的实现。Iterable是提供Iterator的接口。


1
如果任何类正在实现Iterable,则应该在其中具有Iterator()方法???如果我错了,请纠正我。
Chinmaya B 2015年

是。它应该具有接口的未实现方法。在这种情况下,它是Iterator。
agent.smith 2015年

感谢您的明智回答。我来这里是要仔细检查我对Iterable vs Iterator的理解。您确认了。所有其他答案都谈论结构,我想这很好,但没有回答为什么我会在另一个上使用的问题。
EricGreg

对我来说,这是最好的答案。
山姆

我想知道For每个循环对于String的好处:someClass。由于someClass是java类对象,所以它是String ref。在这种情况下,应该使用这种实现。
Neeraj

8

最重要的考虑因素是所讨论的项目是否应该能够被多次遍历。这是因为您始终可以通过再次调用iterator()来回退Iterable,但是无法回退Iterator。


我想知道为什么集合类不能直接实现Iterator接口(而不是实现Iterable和返回Iterator对象)。这个答案清楚地表明-在这种情况下,不可能多次遍历collection(并且不能同时遍历多个线程)。这是非常重要的答案。
simpleDev

2

正如解释这里,将“ 可迭代 ”被引入到能够在使用foreach循环。可以迭代实现Iterable接口的类。

Iterator是管理Iterable上的迭代的类。它保持我们在当前迭代中的位置的状态,并且知道下一个元素是什么以及如何获取它。


2

考虑一个有10个苹果的例子。当它实现Iterable时,就像将每个苹果放在1到10的盒子中并返回一个可用于导航的迭代器一样。

通过实现迭代器,我们可以获取任何苹果,下一盒苹果等。

因此,实现iterable使迭代器可以导航其元素,尽管要导航,则需要实现迭代器。


1

问题:可迭代与迭代器之间的区别?
答:

iterable:与forEach循环
迭代器有关:与Collection有关

forEach循环的目标元素应该是可迭代的。
我们可以使用Iterator从Collection中一个接一个地获取对象

java.ḷang包中
存在的Iterable java.util包中存在的迭代器

仅包含一个方法iterator()
包含三个方法hasNext(),next(),remove()

在1.5版本中
引入在1.2版本中引入


1

基本上,两者彼此之间有着非常紧密的联系。

Iterator视为一个接口,可以借助一些未定义的方法(例如hasNext(),next()和remove())帮助我们遍历集合。

另一方面,Iterable是另一个接口,如果由类实现,则该接口将强制该类为Iterable,并且是For-Each构造的目标。它只有一个名为iterator()的方法,该方法来自Iterator接口本身。

如果集合是可迭代的,则可以使用迭代器对其进行迭代。

要了解,请访问以下网址:

ITERABLE: http ://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/lang/Iterable.java

实验者 http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/Iterator.java


0

除了ColinDSeeker答案。

简单来说,IterableIterator都是Java的Collection Framework中提供的接口。

可迭代的

如果一个类希望有一个for-each循环来迭代其集合,则必须实现Iterable接口。但是,for-each循环只能用于向前循环浏览集合,而您将无法修改该集合中的元素。但是,如果您只想读取元素数据,那么它非常简单,而且由于使用Java lambda表达式,它通常只是一个衬里。例如:

iterableElements.forEach (x -> System.out.println(x) );

迭代器

该接口使您可以遍历集合,获取和删除其元素。每个集合类都提供一个iterator()方法,该方法将迭代器返回到集合的开头。该接口优于可迭代的优点是,使用此接口可以添加,修改或删除集合中的元素。但是,访问元素需要比可迭代更多的代码。例如:

for (Iterator i = c.iterator(); i.hasNext(); ) {
       Element e = i.next();    //Get the element
       System.out.println(e);    //access or modify the element
}

资料来源:

  1. Java Doc Iterable
  2. Java Doc迭代器

0

Iterable 被介绍用于Java中的每个循环

public interface Collection<E> extends Iterable<E>  

Iterator是管理上的迭代的类Iterable。它保持我们在当前迭代中的位置的状态,并且知道下一个元素是什么以及如何获取它。


欢迎使用SO,您可以随时在这里进行浏览,这样您的回答将更加有用和干净。在我们的案例中,问题是要对这两个类进行解释,但是您的答案很混乱,而不是清除所有内容。在发布来自已知/有效/认证来源的摘要时,也请尝试保留引用,以使您的答案更加具体。
AntJavaDev
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.