ArrayList和LinkedList的几种循环遍历方式及性能对比分析.docx
- 文档编号:26654898
- 上传时间:2023-06-21
- 格式:DOCX
- 页数:14
- 大小:21.04KB
ArrayList和LinkedList的几种循环遍历方式及性能对比分析.docx
《ArrayList和LinkedList的几种循环遍历方式及性能对比分析.docx》由会员分享,可在线阅读,更多相关《ArrayList和LinkedList的几种循环遍历方式及性能对比分析.docx(14页珍藏版)》请在冰豆网上搜索。
ArrayList和LinkedList的几种循环遍历方式及性能对比分析
主要介绍ArrayList和LinkedList这两种list的五种循环遍历方式,各种方式的性能测试对比,根据ArrayList和LinkedList的源码实现分析性能结果,总结结论。
通过本文你可以了解
(1)List的五种遍历方式及各自性能
(2)foreach及Iterator的实现(3)加深对ArrayList和LinkedList实现的了解。
阅读本文前希望你已经了解ArrayList顺序存储和LinkedList链式的结构,本文不对此进行介绍。
相关:
HashMap循环遍历方式及其性能对比
1.List的五种遍历方式
下面只是简单介绍各种遍历示例(以ArrayList为例),各自优劣会在本文后面进行分析给出结论。
(1)foreach循环
Java
1
2
3
4
List
for(Integerj:
list){
//usej
}
(2)显示调用集合迭代器
Java
1
2
3
4
List
for(Iterator
iterator.next();
}
或
Java
1
2
3
4
5
List
Iterator
while(iterator.hasNext()){
iterator.next();
}
(3)下标递增循环,终止条件为每次调用size()函数比较判断
Java
1
2
3
4
List
for(intj=0;j list.get(j); } (4)下标递增循环,终止条件为和等于size()的临时变量比较判断 Java 1 2 3 4 5 List intsize=list.size(); for(intj=0;j list.get(j); } (5)下标递减循环 Java 1 2 3 4 List for(intj=list.size()-1;j>=0;j--){ list.get(j); } 在测试前大家可以根据对ArrayList和LinkedList数据结构及Iterator的了解,想想上面五种遍历方式哪个性能更优。 2、List五种遍历方式的性能测试及对比 以下是性能测试代码,会输出不同数量级大小的ArrayList和LinkedList各种遍历方式所花费的时间。 ArrayList和LinkedList循环性能对比测试代码 PS: 如果运行报异常inthread“main”java.lang.OutOfMemoryError: Javaheapspace,请将main函数里面listsize的大小减小。 其中getArrayLists函数会返回不同size的ArrayList,getLinkedLists函数会返回不同size的LinkedList。 loopListCompare函数会分别用上面的遍历方式1-5去遍历每一个list数组(包含不同大小list)中的list。 print开头函数为输出辅助函数。 测试环境为Windows732位系统3.2G双核CPU4G内存,Java7,Eclipse-Xms512m-Xmx512m 最终测试结果如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 compareloopperformanceofArrayList ----------------------------------------------------------------------- listsize |10,000 |100,000 |1,000,000|10,000,000 ----------------------------------------------------------------------- foreach |1ms |3ms |14ms |152ms ----------------------------------------------------------------------- foriterator |0ms |1ms |12ms |114ms ----------------------------------------------------------------------- forlist.size() |1ms |1ms |13ms |128ms ----------------------------------------------------------------------- forsize=list.size()|0ms |0ms |6ms |62ms ----------------------------------------------------------------------- forj-- |0ms |1ms |6ms |63ms ----------------------------------------------------------------------- compareloopperformanceofLinkedList ----------------------------------------------------------------------- listsize |100 |1,000 |10,000 |100,000 ----------------------------------------------------------------------- foreach |0ms |1ms |1ms |2ms ----------------------------------------------------------------------- foriterator |0ms |0ms |0ms |2ms ----------------------------------------------------------------------- forlist.size() |0ms |1ms |73ms |7972ms ----------------------------------------------------------------------- forsize=list.size()|0ms |0ms |67ms |8216ms ----------------------------------------------------------------------- forj-- |0ms |1ms |67ms |8277ms ----------------------------------------------------------------------- 第一张表为ArrayList对比结果,第二张表为LinkedList对比结果。 表横向为同一遍历方式不同大小list遍历的时间消耗,纵向为同一list不同遍历方式遍历的时间消耗。 PS: 由于首次遍历List会稍微多耗时一点,foreach的结果稍微有点偏差,将测试代码中的几个Type顺序调换会发现,foreach耗时和foriterator接近。 3、遍历方式性能测试结果分析 (1)foreach介绍 foreach是JavaSE5.0引入的功能很强的循环结构,for(Integerj: list)应读作foreachintinlist。 for(Integerj: list)实现几乎等价于 Java 1 2 3 4 Iterator while(iterator.hasNext()){ Integerj=iterator.next(); } 下面的分析会将foreach和显示调用集合迭代器两种遍历方式归类为Iterator方式,其他三种称为get方式遍历。 这时我们已经发现foreach的一大好处,简单一行实现了四行的功能,使得代码简洁美观,另一大好处是相对于下标循环而言的,foreach不必关心下标初始值和终止值及越界等,所以不易出错。 Effective-Java中推荐使用此种写法遍历,本文会验证这个说法。 使用foreach结构的类对象必须实现了Iterable接口,Java的Collection继承自此接口,List实现了Collection,这个接口仅包含一个函数,源码如下: Java 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 packagejava.lang; importjava.util.Iterator; /** *Implementingthisinterfaceallowsanobjecttobethetargetof *the"foreach"statement. * *@param * *@since1.5 */ publicinterfaceIterable /** *ReturnsaniteratoroverasetofelementsoftypeT. * *@returnanIterator. */ Iterator } iterator()用于返回一个Iterator,从foreach的等价实现中我们可以看到,会调用这个函数得到Iterator,再通过Iterator的next()得到下一个元素,hasNext()判断是否还有更多元素。 Iterator源码如下: Java 1 2 3 4 5 6 7 publicinterfaceIterator booleanhasNext(); Enext(); voidremove(); } (2)ArrayList遍历方式结果分析 1 2 3 4 5 6 7 8 9 10 11 12 13 14 compareloopperformanceofArrayList ----------------------------------------------------------------------- listsize |10,000 |100,000 |1,000,000|10,000,000 ----------------------------------------------------------------------- foreach |1ms |3ms |14ms |152ms ----------------------------------------------------------------------- foriterator |0ms |1ms |12ms |114ms ----------------------------------------------------------------------- forlist.size() |1ms |1ms |13ms |128ms ----------------------------------------------------------------------- forsize=list.size()|0ms |0ms |6ms |62ms ----------------------------------------------------------------------- forj-- |0ms |1ms |6ms |63ms ----------------------------------------------------------------------- PS: 由于首次遍历List会稍微多耗时一点,foreach的结果稍微有点偏差,将测试代码中的几个Type顺序调换会发现,foreach耗时和foriterator接近。 从上面我们可以看出: a.在ArrayList大小为十万之前,五种遍历方式时间消耗几乎一样 b.在十万以后,第四、五种遍历方式快于前三种,get方式优于Iterator方式,并且 Java 1 2 3 4 intsize=list.size(); for(intj=0;j list.get(j); } 用临时变量size取代list.size()性能更优。 我们看看ArrayList中迭代器Iterator和get方法的实现 Java 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 privateclassItrimplementsIterator intcursor; //indexofnextelementtoreturn intlastRet=-1;//indexoflastelementreturned;-1ifnosuch intexpectedModCount=modCount; publicbooleanhasNext(){ returncursor! =size; } @SuppressWarnings("unchecked") publicEnext(){ checkForComodification(); inti=cursor; if(i>=size) thrownewNoSuchElementException(); Object[]elementData=ArrayList.this.elementData; if(i>=elementData.length) thrownewConcurrentModificationException(); cursor=i+1; return(E)elementData[lastRet=i]; } …… } publicEget(intindex){ rangeCheck(index); returnelementData(index); } 从中可以看出get和Iterator的next函数同样通过直接定位数据获取元素,只是多了几个判断而已。 c.从上可以看出即便在千万大小的ArrayList中,几种遍历方式相差也不过50ms左右,且在常用的十万左右时间几乎相等,考虑foreach的优点,我们大可选用foreach这种简便方式进行遍历。 (3)LinkedList遍历方式结果分析 1 2 3 4 5 6 7 8 9 10 11 12 13 14 compareloopperformanceofLinkedList ----------------------------------------------------------------------- listsize |100 |1,000 |10,000 |100,000 ----------------------------------------------------------------------- foreach |0ms |1ms |1ms |2ms ----------------------------------------------------------------------- foriterator |0ms |0ms |0ms |2ms ----------------------------------------------------------------------- forlist.size() |0ms |1ms |73ms |7972ms ----------------------------------------------------------------------- forsize=list.size()|0ms |0ms |67ms |8216ms ----------------------------------------------------------------------- forj-- |0ms |1ms |67ms |8277ms ----------------------------------------------------------------------- PS: 由于首次遍历List会稍微多耗时一点,foreach的结果稍微有点偏差,将测试代码中的几个Type顺序调换会发现,foreach耗时和foriterator接近。 从上面我们可以看出: a在LinkedList大小接近一万时,get方式和Iterator方式就已经差了差不多两个数量级,十万时Iterator方式性能已经远胜于get方式。 我们看看LinkedList中迭代器和get方法的实现 Java 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 privateclassListItrimplementsListIterator privateNode privateNode privateintnextIndex; privateintexpectedModCount=modCount; ListItr(intindex){ //assertisPositionIndex(index); next=(index==size)? null: node(index); nextIndex=index; } publicbooleanhasNext(){ returnnextIndex } publicEnext(){ checkForComodification(); if(! hasNext()) thrownewNoSuchElementException(); lastReturned=next; next=next.next; nextIndex++; returnlastReturned.item; } …… } publi
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- ArrayList LinkedList 循环 遍历 方式 性能 对比 分析