Java 为什么通过LinkedList的迭代速度很慢?
爪哇8 我有一个相当大的集合(大约100万个元素),我需要遍历它并执行一些操作。有两种选择:Java 为什么通过LinkedList的迭代速度很慢?,java,performance,list,Java,Performance,List,爪哇8 我有一个相当大的集合(大约100万个元素),我需要遍历它并执行一些操作。有两种选择: 迭代一次并完成整个工作(这会使代码变得非常复杂) 迭代两次,在第一次迭代中完成一半工作,在第二次迭代中完成其余工作(这将大大简化代码) 因此,我认为迭代并不昂贵,并编写了一个简单的示例来衡量它(我不经常编写基准测试,因此它可能看起来有点傻): Collection col=newlinkedlist(); 对于(int i=0;i有很多的去装箱/装箱正在发生,这确实对性能有影响。 但除此之外,你必须知道
Collection col=newlinkedlist();
对于(int i=0;i<30000000;i++){
col.add(数学sqrt(i+1));
}
long start1=System.nanoTime();
双精度=0.0;
for(双d:col){
res+=d+d;
}
long-end1=System.nanoTime();
System.out.println(end1-start1);
System.out.println(“=======================================================”);
long start2=System.nanoTime();
双res2=0.0;
for(双d:col){
res2+=d;
}
for(双d:col){
res2+=d;
}
long-end2=System.nanoTime();
System.out.println(end2-start2);
平均结果如下:
1107881047
2133450162
秒(速度慢一倍)
所以,迭代是一个相当缓慢的过程。但我不明白为什么?我认为我们做的工作量几乎相同,所以表现会有很大不同 值得注意的是,如果我使用
ArrayList
而不是链表,结果是:
3858616604
422297749
Second(比第一个快十倍,比上例快两倍)
你不能简单地解释一下这种性能差异吗?我认为有几个原因导致了你所看到的性能下降
int
,float
等)并将其放入其等价类(即,Integer
,float
等)时,基元值都会被装箱。当需要将其用作基本体时,需要将其取消装箱。这里的要点是这样做需要CPU周期和时间
可以提供有关自动装箱的更多详细信息
算法
简单地说,您使用的只在列表上迭代一次的算法是O(n)
,而您使用的需要两次迭代的实现现在是O(2n)
。两者仍然是O(n),但都知道Big-O是一个渐近上界,而不是“性能”的度量。应该仍然清楚的是,在同一个列表上迭代两次所需的工作量大约是仅在该列表上迭代一次所需工作量的两倍
算法和自动装箱相结合产生了显著的效果,您可以在如下代码中看到:
for(int i = 0; i < reallyLargeNumberHere; i++){
col.add(Math.sqrt(i + 1));
}
for(int i=0;i
sqrt
计算本身很昂贵,需要进行自动装箱来添加每个元素。尽管如此,对大型列表的双重迭代将是罪魁祸首
简言之
O(n)
罚款sqrt
算法本身速度很慢O(1)
,但对于迭代/搜索则不是这样——它们往往是O(n)
<>最后,对于简单的目的,使用<代码> Stase.NimeTime/Cord>可能是OK,如果你想做更严肃的事情,你应该考虑使用一个专门设计的工具来测试代码。 < P>有很多的去装箱/装箱正在发生,这确实对性能有影响。 但除此之外,你必须知道数组和链表之间的区别 在阵列中,为阵列分配一个连续的内存块。因此,元素的随机访问是可能的 所以当我想得到一个大数组的第5000个元素时,它会在瞬间返回它 时间复杂性 访问元素=O(1) 但在链表中,不能随机访问元素。要访问某个元素,您需要遍历链表,直到找到所需的元素 所以,如果我访问第三个元素,在内部它会像 1->2->3,返回第三个元素 第一个元素没有关于第三个元素的任何信息,它只有到第二个元素的链接 时间复杂性 访问元素=O(n) 在决定使用哪种类型的集合时,您需要了解数据结构和时间复杂性的概念。因为在大型数据集中,它可能会导致巨大的性能差异 您可以参考此链接了解时间复杂性:
首先,对于基准测试,您最好使用 现在,到
for(int i = 0; i < reallyLargeNumberHere; i++){
col.add(Math.sqrt(i + 1));
}
//First:
for(Double d : col){
res += d + d;
}
//Second
for(Double d : col){
res2 += d;
}
for(Double d : col){
res2 += d;
}
LinkedList<String> linkedList = new LinkedList<String>();
linkedList.add("eBay");
linkedList.add("Paypal");
linkedList.add("Google");
linkedList.add("Yahoo");
linkedList.add("IBM");
linkedList.add("Facebook");
// ListIterator approach
System.out.println("ListIterator Approach: ");
ListIterator<String> listIterator = linkedList.listIterator();
while (listIterator.hasNext()) {
System.out.println(listIterator.next());
}