首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >为什么遍历列表会比索引更快呢?

为什么遍历列表会比索引更快呢?
EN

Stack Overflow用户
提问于 2012-05-08 01:38:17
回答 5查看 14.6K关注 0票数 125

阅读Java documentation for the ADT List时,它会说:

List接口提供了四种对列表元素进行位置(索引)访问的方法。列表(像Java数组)是从零开始的。请注意,对于某些实现(例如,LinkedList类),这些操作的执行时间可能与索引值成比例。因此,如果调用者不知道实现,那么迭代列表中的元素通常比索引列表中的元素更可取。

这到底是什么意思?我不明白所得出的结论。

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2012-05-08 01:44:35

在链表中,每个元素都有一个指向下一个元素的指针:

代码语言:javascript
复制
head -> item1 -> item2 -> item3 -> etc.

要访问item3,您可以清楚地看到,您需要从头部遍历每个节点,直到到达item3,因为您不能直接跳转。

因此,如果我想打印每个元素的值,如果我这样写:

代码语言:javascript
复制
for(int i = 0; i < 4; i++) {
    System.out.println(list.get(i));
}

事情是这样的:

代码语言:javascript
复制
head -> print head
head -> item1 -> print item1
head -> item1 -> item2 -> print item2
head -> item1 -> item2 -> item3 print item3

这是非常低效的,因为每次你索引的时候,它都会从列表的开头重新开始,遍历每一项。这意味着你的复杂性是有效的O(N^2),仅仅是为了遍历列表!

如果我这样做:

代码语言:javascript
复制
for(String s: list) {
    System.out.println(s);
}

然后会发生这样的事情:

代码语言:javascript
复制
head -> print head -> item1 -> print item1 -> item2 -> print item2 etc.

所有操作都在一次遍历中完成,这就是O(N)

现在,转到List的另一个实现,也就是ArrayList,它由一个简单的数组支持。在这种情况下,上面的两次遍历都是等效的,因为数组是连续的,所以它允许随机跳转到任意位置。

票数 211
EN

Stack Overflow用户

发布于 2012-05-08 01:41:16

答案隐含在这里:

请注意,对于某些实现(例如,LinkedList类),这些操作的执行时间可能与索引值成比例

链表没有固有的索引;调用.get(x)需要列表实现找到第一个条目并调用.next() x-1次(对于O(n)或线性时间访问),其中基于数组的列表只能在O(1)或恒定时间内索引到backingarray[x]

如果您查看JavaDoc for LinkedList,您将看到以下注释

所有操作的执行与双向链表的预期一致。索引到列表中的操作将从开头或结尾遍历列表,以更接近指定索引的那个为准。

JavaDoc for ArrayList具有对应的

Resizable- List接口的数组实现。实现所有可选的列表操作,并允许所有元素,包括null。除了实现list接口之外,该类还提供了一些方法来操作内部用于存储列表的数组的大小。(这个类大体上等同于Vector,只是它是不同步的。)

sizeisEmptygetsetiteratorlistIterator操作在固定时间内运行。add操作在分期固定时间内运行,即添加n个元素需要O(n)时间。所有其他操作都在线性时间内运行(粗略地说)。与LinkedList实现相比,常量因子较低。

一个related question titled "Big-O Summary for Java Collections Framework"有一个指向这个资源"Java Collections JDK6"的答案,你可能会发现它对你有帮助。

票数 35
EN

Stack Overflow用户

发布于 2012-05-09 11:26:16

使用偏移量遍历列表以进行查找,例如i,类似于画家Shlemiel的算法。

Shlemiel找到了一份街道油漆工的工作,他在路中间画虚线。第一天,他带着一罐油漆上路,完成了300码的路程。“这真是太好了!”他的老板说:“你干得真快!”然后付给他一个科比。

第二天,施莱米尔只完成了150码。“嗯,这远没有昨天那么好,但你仍然是一个速度很快的工人。150码是值得尊敬的,”他付给他一个科比。

第二天,施莱米尔画了30码的路。“只有30个!”他的老板喊道。“这是不能接受的!第一天你就做了十倍的工作!这是怎么回事?”

“我忍不住,”施莱米尔说。“我一天比一天离油漆罐越来越远!”

Source

这个小故事可能会让我们更容易理解内部发生的事情,以及为什么它如此低效。

票数 8
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10486507

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档