ArrayList与LinkedList遍历方式对比及List遍历技巧

简介: ArrayList与LinkedList遍历方式对比及List遍历技巧

ArrayList遍历方式

首先在主函数中调用ArrayList的构造方法生成一个size为一亿的,element全为aList实例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全为aList实例list

int max = 100000;
List<String> list = new LinkedList<>();
for (int i = 0; i < max; i++) {
    list.add("a");
}

对于其他遍历方式,使用LinkedList的构造方法生成一个size为一亿的,element全为aList实例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遍历方式分析

  1. 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));
}
目录
相关文章
|
5月前
|
存储 Java
Java学习笔记 List集合的定义、集合的遍历、迭代器的使用
Java学习笔记 List集合的定义、集合的遍历、迭代器的使用
|
27天前
|
Java 机器人 程序员
从入门到精通:五种 List 遍历方法对比与实战指南
小米是一位热爱分享技术的程序员,本文详细介绍了 Java 中遍历 List 的五种方式:经典 for 循环、增强 for 循环、Iterator 和 ListIterator、Stream API 以及 forEach 方法。每种方式都有其适用场景和优缺点,例如 for 循环适合频繁访问索引,增强 for 循环和 forEach 方法代码简洁,Stream API 适合大数据量操作,ListIterator 支持双向遍历。文章通过生动的小故事和代码示例,帮助读者更好地理解和选择合适的遍历方式。
57 2
|
3月前
|
Java 程序员 编译器
Java|如何正确地在遍历 List 时删除元素
从源码分析如何正确地在遍历 List 时删除元素。为什么有的写法会导致异常,而另一些不会。
68 3
|
3月前
|
设计模式 安全 容器
数据结构第一篇【探究List和ArrayList之间的奥秘 】
数据结构第一篇【探究List和ArrayList之间的奥秘 】
31 5
|
6月前
|
存储 安全 Java
详解Java中集合的List接口实现的ArrayList方法 | Set接口实现的HashSet方法
详解Java中集合的List接口实现的ArrayList方法 | Set接口实现的HashSet方法
|
7月前
|
Java 索引
Java List实战:手把手教你玩转ArrayList和LinkedList
【6月更文挑战第17天】在Java中,ArrayList和LinkedList是List接口的实现,分别基于动态数组和双向链表。ArrayList适合索引访问,提供快速读取,而LinkedList擅长插入和删除操作。通过示例展示了两者的基本用法,如添加、访问、修改和删除元素。根据场景选择合适的实现能优化性能。
60 0
|
7月前
|
Java 开发者 索引
Java List全攻略:从ArrayList到LinkedList,一网打尽!
【6月更文挑战第17天】Java List详解:ArrayList依赖动态数组,擅长随机访问和遍历,适合少次插入删除;LinkedList基于双向链表,插入删除高效,尤其在头尾操作,但随机访问慢。选择取决于应用场景,理解特性以优化代码。探索ArrayList与LinkedList,提升编程效率!
87 0
|
7月前
|
安全 Java
java线程之List集合并发安全问题及解决方案
java线程之List集合并发安全问题及解决方案
1093 1
|
6月前
|
Java API Apache
怎么在在 Java 中对List进行分区
本文介绍了如何将列表拆分为给定大小的子列表。尽管标准Java集合API未直接支持此功能,但Guava和Apache Commons Collections提供了相关API。
|
6月前
|
运维 关系型数据库 Java
PolarDB产品使用问题之使用List或Range分区表时,Java代码是否需要进行改动
PolarDB产品使用合集涵盖了从创建与管理、数据管理、性能优化与诊断、安全与合规到生态与集成、运维与支持等全方位的功能和服务,旨在帮助企业轻松构建高可用、高性能且易于管理的数据库环境,满足不同业务场景的需求。用户可以通过阿里云控制台、API、SDK等方式便捷地使用这些功能,实现数据库的高效运维与持续优化。