“嗨,阿米戈!”
“嗨,艾莉!”
“今天我想给大家讲讲迭代器。”
“迭代器实际上是与集合同时发明的。集合的主要目的是存储元素,而迭代器的主要目的是一个一个地检索这些元素。”
“搞到一套元素有什么难的?”
“首先,一些集合中的元素,例如 Set,没有既定的顺序和/或顺序不断变化。”
“其次,一些数据结构可能以非常复杂的方式存储对象:在不同的组、列表等中。换句话说,按顺序分发所有元素将是一项非常重要的任务。”
“第三,集合往往会发生变化。假设您决定显示集合的全部内容,但就在输出中间,JVM 切换到另一个线程,该线程替换了集合的一半元素。因此,您得到的不是输出,而是谁知道呢。”
“唔...”
“但是!这些正是迭代器可以解决的问题。迭代器是集合中的一个特殊对象,一方面可以访问其所有私有数据并知道其内部结构,另一方面,实现了公共 Iterator 接口,让每个人都知道如何使用它。 ”
“一些迭代器有一个内部数组,当创建迭代器时,集合中的所有元素都会被复制到这个数组中。这确保了对集合的任何后续更改都不会影响元素的数量或顺序。”
“我认为你在使用for each时遇到过这个问题。你不能同时遍历一个集合并从中删除元素。这完全是因为迭代器的工作方式。”
“在添加到并发库的新集合中,迭代器被重新设计以消除这个问题。”
“让我提醒你迭代器是如何工作的。”
“Java 有一个特殊的 Iterator 接口。这是它的方法:”
Iterator<E> 接口的方法 | 描述 |
---|---|
boolean hasNext() |
检查是否还有更多元素 |
E next() |
返回当前元素并移动到下一个。 |
void remove() |
移除当前元素 |
“迭代器可让您连续获取集合的所有元素。将迭代器视为类似于 InputStream 的东西更合乎逻辑——它拥有所有数据,但其任务是按顺序输出数据。”
“ next () 方法返回集合中的下一个元素。”
“ hasNext () 方法用于检查是否还有更多元素。”
“而remove () 移除当前元素。”
“任何问题?”
“为什么这些方法有这么奇怪的名字?为什么不是 isEmpty() 和 getNextElement()?”
“那不是更有意义吗?”
“这会更有意义,但名称来自 C++ 语言,其中迭代器出现得更早。”
“原来如此,我们继续吧。”
“除了迭代器,还有一个Iterable接口,所有支持迭代器的集合都必须实现这个接口,它只有一个方法:”
Iterable<T> 接口的方法 | 描述 |
---|---|
Iterator<T>iterator() |
返回一个迭代器对象 |
“您可以在任何集合上使用此方法来获取迭代器对象以遍历其元素。让我们遍历 TreeSet 中的所有元素: ”
TreeSet<String> set = new TreeSet<String>();
Iterator<String> iterator = set.iterator();
while (iterator.hasNext())
{
String item = iterator.next();
System.out.println(item);
}
“像这样使用迭代器不是很方便——有太多多余和明显的代码。当for-each循环出现在 Java 中时,情况变得更简单了。”
“现在这段代码更加紧凑和可读:”
前 | 后 |
---|---|
|
|
“这是相同的代码!两种情况下都使用了迭代器。”
“只是它的使用隐藏在for-each循环中,注意右边的代码根本没有红字,完全隐藏了迭代器的使用。”
“ for-each循环可用于支持迭代器的任何对象。换句话说,您可以编写自己的类,向其添加 iterator ( ) 方法,并在for-each构造中使用其对象。”
“哇!当然,我并不急于编写自己的集合和迭代器,但前景仍然很诱人。我会记下来的。”
此外,还有另一种流行的迭代器类型,它甚至有自己的接口。我说的是列表迭代器,即ListIterator。
“不管它们的实现如何,列表都会保持元素的顺序,这使得通过迭代器使用它们更方便一些。”
“这是ListIterator <E> 接口的方法:”
方法 | 描述 |
---|---|
boolean hasNext() |
检查前面是否还有更多元素。 |
E next() |
返回下一个元素。 |
int nextIndex() |
返回下一个元素的索引 |
void set(E e) |
改变当前元素的值 |
boolean hasPrevious() |
检查后面是否有任何元素。 |
E previous() |
返回前一个元素 |
int previousIndex() |
返回前一个元素的索引 |
void remove() |
移除当前元素 |
void add(E e) |
将一个元素添加到列表的末尾。 |
“换句话说,在这里我们可以向前和向后移动。还有一些其他的小特征。”
“嗯,那是个有趣的东西。它用在什么地方?”
“假设你想在链表上来回移动。get 操作会相当慢,但 next() 操作会非常快。”
“嗯,你说服了我,我会记住的。”
“谢谢,艾莉!”
GO TO FULL VERSION