迭代器保证有以下方法:
- 有下一个()
- 下一个()
- 删除(可选)
当for-each
循环遍历iterable
类对象时,它如何知道从哪个对象开始?上述方法提供了清晰的前进路径,但什么指向起始元素?
For-each
保证遍历所有相关对象。根据一个类及其next()
实现,从哪里开始可能非常重要(考虑forward linked list
或任何其他具有root
元素的实现)。
它是如何工作的?
如果我的问题没有意义,请解释原因。
您可能想查看内部类的ArrayList
实现。Iterator
Itr
private class Itr implements Iterator<E> {
int cursor; // index of next element to return
int lastRet = -1; // index of last element returned; -1 if no such
int expectedModCount = modCount;
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];
}
...
}
cursor
默认初始化为0
。您用于cursor
访问ArrayList
对象的支持数组中的元素(它是一个内部类,它可以访问该字段)。
类似的逻辑适用于Iterator
. 它始终取决于底层数据结构。作为另一个例子, aSet
不应该有一个排序,但它确实实现了Iterator
. 必须决定迭代器从哪里开始。
官方称为增强for
语句( for(E e: Iterable<E> iterable)
) 的内容由编译器翻译成等效于以下代码:
E e;
for(Iterator<E> it = iterable.iterator(); it.hasNext(); ) {
e = it.next();
// contents of your for loop
}
循环的行为就像你用一个明确的 编写它一样,所以增强循环Iterator
的“起点”是无论如何都应该开始的地方。for
iterable.iterator()
foreach 是从 first 到 last 的 for 循环的简写。
这一切都取决于您的收藏。
如果您的集合是一个列表(ArrayList
或LinkedList
通常),那么迭代器将根据它们的插入方式按列表顺序排列。
如果是 Map 或 Set,则很难预测其成员的顺序。如果您使用的是 Map 或 Set,则实际上不应指望任何可预测的排序,因为它不符合这些集合的目的。但是,如果您需要特定订单但还需要 Map 或 Set 的功能,则可以使用 or LinkedHashMap
。LinkedHashSet