Answers:
在链接列表中,每个元素都有一个指向下一个元素的指针:
head -> item1 -> item2 -> item3 -> etc.
要访问item3
,您可以清楚地看到您需要从头经过每个节点直到到达item3,因为您不能直接跳转。
因此,如果我想打印每个元素的值,请编写以下代码:
for(int i = 0; i < 4; i++) {
System.out.println(list.get(i));
}
这是怎么回事:
head -> print head
head -> item1 -> print item1
head -> item1 -> item2 -> print item2
head -> item1 -> item2 -> item3 print item3
这是非常低效的,因为每次索引时,它都会从列表的开头重新开始并遍历每个项目。这意味着您的复杂性实际上O(N^2)
只是遍历列表!
如果相反,我这样做:
for(String s: list) {
System.out.println(s);
}
那么会发生什么:
head -> print head -> item1 -> print item1 -> item2 -> print item2 etc.
全部在一个遍历中,即O(N)
。
现在,转到另一种实现,List
该实现ArrayList
由一个简单数组支持。在这种情况下,上述两个遍历都是等效的,因为数组是连续的,因此它允许随机跳转到任意位置。
REVERSE_THRESHOLD
设置为18 in java.util.Collections
,很奇怪地看到这么高的答案而没有评论。
List l = unknownList(); if (l instanceof RandomAccess) /* do indexed loop */ else /* use iterator/foreach */
答案暗示在这里:
请注意,在某些实现中,这些操作可能会按与索引值成比例的时间执行(例如,LinkedList类)
链表没有内在的索引。调用.get(x)
将要求列表实现找到第一个条目并调用.next()
x-1次(对于O(n)或线性时间访问),其中数组支持的列表可以只索引backingarray[x]
O(1)或恒定时间。
如果您查看的JavaDocLinkedList
,将会看到注释
所有操作均按双向链表的预期执行。索引到列表中的操作将从开头或结尾遍历列表,以更接近指定索引的位置为准。
而JavaDoc forArrayList
具有相应的
List接口的可调整大小的数组实现。实现所有可选的列表操作,并允许所有元素,包括null。除了实现List接口之外,此类还提供一些方法来操纵内部用于存储列表的数组的大小。(此类与Vector大致等效,但它是不同步的。)
的
size
,isEmpty
,get
,set
,iterator
,和listIterator
操作在固定时间运行。加法运算以固定的固定时间运行,也就是说,添加n个元素需要O(n)时间。所有其他操作均以线性时间运行(大致而言)。与LinkedList
实现相比,常数因子低。
名为“ Java集合框架的Big-O摘要”的相关问题有一个指向该资源“ Java集合JDK6”的答案,您可能会发现有帮助。
尽管公认的答案肯定是正确的,但我是否可以指出一个小缺陷。报价都铎王朝:
现在,转到List的另一个实现,即ArrayList,该实现由一个简单数组支持。在这种情况下,上述两个遍历都是等效的,因为数组是连续的,因此它允许随机跳转到任意位置。
这不是完全正确的。事实是,
使用ArrayList时,手写计数循环的速度快大约3倍
资料来源:Google的Android文档,“为性能而设计”
请注意,手写循环是指索引迭代。我怀疑是因为迭代器与增强的for循环一起使用。在以连续数组为后盾的结构中,它在惩罚性能上产生较小的性能。我也怀疑这对于Vector类可能是正确的。
我的规则是,尽可能使用增强的for循环,如果您确实关心性能,请仅对ArrayList或Vector使用索引迭代。在大多数情况下,您甚至可以忽略这一点-编译器可能会在后台对其进行优化。
我只想指出,在Android开发中,ArrayLists的遍历不一定相等。值得深思。
遍历一个具有偏移量的列表以进行查找,例如i
,类似于画家的算法Shlemiel。
Shlemiel从事街头画家的工作,在路中间画了虚线。第一天,他将一罐油漆带到公路上,完成了300码的道路。“那太好了!” 他的老板说:“你是个快劳!” 付给他一个科比
第二天,Shlemiel只完成了150码。“嗯,那还不及昨天,但是你仍然是个快劳。150码是可敬的。”
第二天,Shlemiel画了这条路的30码。“只有30个!” 叫他的老板。“那是不可接受的!第一天,你做了十倍的工作!这是怎么回事?”
“我无能为力,” Shlemiel说。“每天我都离油漆罐越来越远了!”
来源。
这个小故事可以使您更容易理解内部发生的事情以及为什么它如此低效。