我是Java新手,我真的对迭代器和可迭代感到困惑。任何人都可以向我解释并举一些例子吗?
14 回答
AnIterable
是一系列可以迭代的元素的简单表示。它没有任何迭代状态,例如“当前元素”。相反,它有一种方法可以生成Iterator
.
AnIterator
是具有迭代状态的对象。它可以让你检查它是否有更多的元素 usinghasNext()
并移动到下一个元素(如果有的话) using next()
。
通常,anIterable
应该能够产生任意数量的有效Iterator
s。
的实现Iterable
是提供Iterator
自身的:
public interface Iterable<T>
{
Iterator<T> iterator();
}
迭代器是一种简单的方法,它允许某些人在没有分配权限的情况下循环遍历数据集合(尽管具有删除的能力)。
public interface Iterator<E>
{
boolean hasNext();
E next();
void remove();
}
请参阅Javadoc。
我将回答这个问题,特别是关于 ArrayList 作为示例,以帮助您更好地理解..
- 可迭代接口强制其子类实现抽象方法'iterator()'。
public interface Iterable { ... abstract Iterator<T> iterator(); //Returns an 'Iterator'(not iterator) over elements of type T. ... }
- 迭代器接口强制其子类实现抽象方法“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. ... }
- ArrayList 实现 List,List 扩展 Collection 和 Collection 扩展 Iterable.. 也就是说,您可以看到类似的关系
'可迭代 <- 集合 <- 列表 <- ArrayList'
. 而 Iterable、Collection 和 List 只是声明了抽象方法 'iterator()' 并且 ArrayList 单独实现了它。
- 我将使用 '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]; } ... } }
- 其他一些方法或类将通过使用 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);
}
}
现在,清楚了吗?:)
我知道这是一个老问题,但对于任何阅读本文的人来说,如果他们遇到同样的问题并且可能对所有术语感到不知所措,这里有一个很好的简单类比来帮助您理解可迭代对象和迭代器之间的区别:
想想公共图书馆。老套。用纸质书。是的,那种图书馆。
一个装满书的书架就像一个可迭代的。你可以看到书架上一排排的书。你可能不知道有多少,但你可以看到它是一本很长的书集。
图书管理员就像迭代器。他可以随时指向一本特定的书。他可以在他指向的那个位置插入/删除/修改/阅读这本书。每次您大喊“下一个!”时,他都会依次指向每本书。给他。所以,你通常会问他:“有下一个吗?”,他会说“是”,你会说“下一个!” 他会指着下一本书。他也知道他什么时候到达了货架的尽头,所以当你问:“有下一个吗?” 他会说“不”。
我知道这有点傻,但我希望这会有所帮助。
如果集合是可迭代的,则可以使用迭代器对其进行迭代(因此可以在 for each 循环中使用)。迭代器是将迭代集合的实际对象。
实现 Iterable 接口允许对象成为“foreach”语句的目标。
class SomeClass implements Iterable<String> {}
class Main
{
public void method()
{
SomeClass someClass = new SomeClass();
.....
for(String s : someClass) {
//do something
}
}
}
Iterator 是一个接口,它具有迭代元素的实现。Iterable 是一个提供 Iterator 的接口。
最重要的考虑是所讨论的项目是否应该能够被多次遍历。这是因为您始终可以通过再次调用 iterator() 来回退 Iterable,但无法回退 Iterator。
正如这里所解释的,“<em>Iterable”被引入以便能够在foreach
循环中使用。实现Iterable接口的类可以被迭代。
Iterator 是管理Iterable上的迭代的类。它维护我们在当前迭代中所处的状态,并且知道下一个元素是什么以及如何获取它。
考虑一个有 10 个苹果的例子。当它实现 Iterable 时,就像将每个苹果放在从 1 到 10 的盒子中,并返回一个可用于导航的迭代器。
通过实现迭代器,我们可以得到任何苹果,下一个盒子里的苹果等。
因此,实现 iterable 提供了一个迭代器来导航其元素,尽管要导航,需要实现迭代器。
问题:Iterable和Iterator的区别?
答:
iterable:与forEach循环相关
迭代器:Is与Collection相关
forEach 循环的目标元素应该是可迭代的。
我们可以使用Iterator从Collection中一一获取对象
存在于 java.ḷang 包中的 Iterable 存在
于 java.util 包中的 Iterator
只包含一个方法 iterator()
包含三个方法 hasNext(), next(), remove()
1.5版本
引入 1.2版本引入
基本上来说,两者的关系非常密切。
将Iterator视为一个接口,它可以帮助我们在一些未定义的方法(如hasNext()、next() 和 remove() )的帮助下遍历集合
另一方面,Iterable是另一个接口,如果由一个类实现,它会强制该类为 Iterable,并且是 For-Each 构造的目标。它只有一个名为 iterator() 的方法,它来自 Iterator 接口本身。
当一个集合是可迭代的,那么它就可以使用一个迭代器进行迭代。
要了解,请访问这些:
可迭代: 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
Iterable
被引入用于java中的每个循环
public interface Collection<E> extends Iterable<E>
Iterator
是管理迭代的类Iterable
。它维护我们在当前迭代中所处的状态,并且知道下一个元素是什么以及如何获取它。
简单来说,Iterable和Iterator都是 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
}
资料来源:
匿名类很容易将 an 转换Iterator
为 anIterable
并允许您使用Iterable
语法(for 循环,forEach()
)。
示例:考虑一个Iterator<T> it
for (T element : new Iterable<T>() {
@Override
public Iterator<T> iterator() {
return it;
}
}) {
//do something with `T element`
}
在函数中抽象
static <T> Iterable<T> toIterable(Iterator<T> it) {
return new Iterable<T>() {
@Override
public Iterator<T> iterator() {
return it;
}
};
}
用法
for (T element: toIterable(it) {
...
}