ArrayList遍历方式
首先在主函数中调用ArrayList
的构造方法生成一个size
为一亿的,element
全为a
的List
实例list
:
int max = 100000000; List<String> list = new ArrayList<>(max); for (int i = 0; i < max; i++) { list.add("a"); }
接下来看一下常用的五种遍历方法以及所需要的运行时间
for loop
long startTime = System.currentTimeMillis(); for (int i = 0; i < list.size(); i++) { list.get(i).hashCode(); } long endTime = System.currentTimeMillis(); System.out.println("for loop: "+(endTime - startTime));
运行结果为:
for loop: 157
for-each loop
long startTime = System.currentTimeMillis(); for (String s : list) { s.hashCode(); } long endTime = System.currentTimeMillis(); System.out.println("for-each loop: "+(endTime - startTime));
运行结果为:
for-each loop: 202
Iterator
long startTime = System.currentTimeMillis(); Iterator<String> iterator = list.iterator(); while (iterator.hasNext()) { iterator.next().hashCode(); } long endTime = System.currentTimeMillis(); System.out.println("Iterator: "+(endTime - startTime));
运行结果为:
Iterator: 177
ListIterator
long startTime = System.currentTimeMillis(); ListIterator<String> listIterator = list.listIterator(); while (listIterator.hasNext()) { listIterator.next().hashCode(); } long endTime = System.currentTimeMillis(); System.out.println("ListIterator: "+(endTime - startTime));
运行结果为:
ListIterator: 176
java8新特性:forEach
long startTime = System.currentTimeMillis(); list.forEach(t -> t.hashCode()); long endTime = System.currentTimeMillis(); System.out.println("forEach: "+(endTime - startTime));
运行结果为:
forEach: 94
ArrayList遍历方式分析
1.除了java8新特性forEach之外,for loop遍历的方式是最快的,这是因为ArrayList类实现了RandomAccess接口,该接口是一个标志性接口,实现了该接口的类可以支持随机访问,使用for loop遍历的方式快过for-each;
2.Iterator与ListIterator实现类似,只不过ListIterator支持previous方法,可以从后向前遍历;
3.for-each的字节码其实是用Iterator实现的;
LinkedList遍历方式
对于for loop
,首先在主函数中调用LinkedList
的构造方法生成一个size
为十万的,element
全为a
的List
实例list
:
int max = 100000; List<String> list = new LinkedList<>(); for (int i = 0; i < max; i++) { list.add("a"); }
对于其他遍历方式,使用LinkedList
的构造方法生成一个size
为一亿的,element
全为a
的List
实例list
:
int max = 100000000; List<String> list = new LinkedList<>(); for (int i = 0; i < max; i++) { list.add("a"); }
接下来看一下常用的五种遍历方法以及所需要的运行时间
for loop
long startTime = System.currentTimeMillis(); for (int i = 0; i < list.size(); i++) { list.get(i).hashCode(); } long endTime = System.currentTimeMillis(); System.out.println("for loop: "+(endTime - startTime));
运行结果为:
for loop: 3644
为什么仅仅十万个数据,使用for loop遍历一次居然需要3000多ms?因为LinkedList的get(index)方法是从LinkedList的头或尾依次遍历得到的,详见:ArrayList与LinkedList获取指定元素对比;
for-each loop
long startTime = System.currentTimeMillis(); for (String s : list) { s.hashCode(); } long endTime = System.currentTimeMillis(); System.out.println("for-each loop: "+(endTime - startTime));
运行结果为:
for-each loop: 401
Iterator
long startTime = System.currentTimeMillis(); Iterator<String> iterator = list.iterator(); while (iterator.hasNext()) { iterator.next().hashCode(); } long endTime = System.currentTimeMillis(); System.out.println("Iterator: "+(endTime - startTime));
运行结果为:
Iterator: 441
ListIterator
long startTime = System.currentTimeMillis(); ListIterator<String> listIterator = list.listIterator(); while (listIterator.hasNext()) { listIterator.next().hashCode(); } long endTime = System.currentTimeMillis(); System.out.println("ListIterator: "+(endTime - startTime));
运行结果为:
ListIterator: 452
java8新特性:forEach
long startTime = System.currentTimeMillis(); list.forEach(t -> t.hashCode()); long endTime = System.currentTimeMillis(); System.out.println("forEach: "+(endTime - startTime));
运行结果为:
forEach: 435
LinkedList遍历方式分析
for-each loop
遍历的方式是最快的,这是因为LinkedList
类没有实现RandomAccess
接口,不支持随机访问,使用for-each loop
遍历的方式快过for loop
;
List遍历技巧
有时候我们仅仅只会得到一个List实例,但我们并不能够知道它的底层实现是ArrayList还是LinkedList或者是其他的类,这是我们如何以最快的速度遍历它呢?
可以判断该实例是否实现了RandomAccess接口,如果实现了该接口,说明支持随机访问,使用for-loop进行遍历最快;否则使for-each loop进行遍历最快。
示例代码如下:
if (list instanceof RandomAccess) { /** * for loop */ long startTime1 = System.currentTimeMillis(); for (int i = 0; i < list.size(); i++) { list.get(i).hashCode(); } long endTime1 = System.currentTimeMillis(); System.out.println("随机访问: "+(endTime1 - startTime1)); } else { /** * for-each loop */ long startTime2 = System.currentTimeMillis(); for (String s : list) { s.hashCode(); } long endTime2 = System.currentTimeMillis(); System.out.println("顺序访问: "+(endTime2 - startTime2)); }