从第 i 个元素开始的迭代器
如果您创建一个直接从LinkedList 的i-th 索引开始的Iterator,您需要知道这也需要O(n)。在LinkedList 中查找元素总是慢。
LinkedList只记住列表的head(和tail)元素。需要通过遍历整个列表来找到其他所有元素。
这是一个双向链表的示意图(Javas LinkedList 也是双向链接的):
因此,如果您从i-th 元素开始创建Iterator,它将从head(或tail)开始,并跟随指针直到i-th 元素。这就像打电话:
list.get(i);
这显然要花费O(n)。
替代方案:ArrayList
如果您需要快速基于索引的访问,也称为随机访问,您可以考虑改用ArrayList。它的结构允许在O(1)中访问(可以直接通过start + i * sizeof(type)计算元素在内存中的位置)。
提供如此快速随机访问的数据结构通常实现接口RandomAccess (documentation and implementing classes) 作为指标。
如何迭代
如上所述,迭代LinkedList 不应通过list.get(i) 的基于索引的访问来完成。因此,您应该使用Iterator(或ListIterator,如果您需要在迭代时修改列表)。
这是使用Iterator 的常用方法:
Iterator<E> iter = list.iterator();
while (iter.hasNext()) {
E element = iter.next();
...
}
或者您也可以使用 增强的 for 循环,它在内部执行相同的操作,但看起来更紧凑:
for (E element : list) {
...
}
由于Javas LinkedList是一个双向链表,你也可以从尾部开始,反向迭代列表。因此只需使用 LinkedList#descendingIterator 方法 (documentation) 而不是 LinkedList#iterator。
最后一个例子展示了如何在迭代时使用ListIterator修改列表:
ListIterator<E> listIter = list.listIterator(0);
while (listIter.hasNext()) {
E element = listIter.next();
...
// Remove the element last polled
listIter.remove();
// Inserts an element right before the last polled element
listIter.add(new Element());
}
您还可以使用ListIterator 和hasPrevious() 和previous() 方法来前后遍历列表。这是它的documentation。