ArrayList的遍历方法及效率问题

ArrayList简介

  • ArrayList是一个动态的数组,它继承了AbstractList类,实现了List、RandomAccess,、Cloneable、 java.io.Serializable接口的集合类。
  • 而LinkedList是一个动态的集合链表,它继承了AbstractSequentialList类,实现了List、Deque、Cloneable、 java.io.Serializable接口的集合类。可以看到,LinkedList并没有去实现RandomAccess这个接口,我们不妨看看RandomAccess接口类是什么

在这里插入图片描述
可以看到,RandomAccess接口仅仅只是一个定义,并没有什么实际意义,通过API上的注释得知,它仅仅是一种标识,标志着实现该类的可以进行随机访问,也就是说ArrayList是支持数组的特性的------随机访问。而LinkedList底层是链表,不支持随机访问。

ArrayList遍历的几种方式

  • 前期工作准备

    Person类

    package com.entity;
    public class Person {
        private Integer id;
        private String name;
        private String sex;
    
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getSex() {
            return sex;
        }
    
        public void setSex(String sex) {
            this.sex = sex;
        }
    
        public Person(Integer id, String name, String sex) {
            this.id = id;
            this.name = name;
            this.sex = sex;
        }
    
        public Person() {
        }
    
        @Override
        public String toString() {
            return "Person{" +
                    "id=" + id +
                    ", name='" + name + '\'' +
                    ", sex='" + sex + '\'' +
                    '}';
        }
    }
    
    
    测试类
    package com.main;
    import com.entity.Person;
    import java.util.ArrayList;
    import java.util.Iterator;
    import java.util.LinkedList;
    import java.util.List;
    
    public class ListTraverse {
        public static void main(String[] args) {
            List<Person> list = new ArrayList<Person>();
            list.add(new Person(1,"braveOne","男"));
            list.add(new Person(2,"braveTwo","男")); 
        }
    }
    
    
  • 使用常见的for循环随机访问,通过索引来进行遍历
    for (int i = 0; i < list.size(); i++) {
        System.out.println(list.get(i));
     }
    
  • 使用增强的for循环进行遍历
    for (Person personList:list){
        System.out.println(personList);
    }
    
  • 使用迭代器Iterator进行遍历
    Iterator<Person> iterator= list.iterator();
      while (iterator.hasNext()){
          System.out.println(iterator.next());
    }
    
  • forEach+Lambda表达式进行遍历
    list.forEach(person -> {
         System.out.println(person);
    });
    
可以发现一共有4中方式来对ArrayList进行遍历,那这四种到低那种方式遍历的效率要高呢?

ArrayList四中遍历方式的效率

测试代码

package com.main;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * \* Created with IntelliJ IDEA.
 * \* User: fight bravely
 * \* Date: 2020/5/4
 * \* Time: 17:48
 * \* To change this template use File | Settings | File Templates.
 * \* Description:
 * \
 *
 * @author 雄
 */
public class ArrayListEfficiency {
    public static void main(String[] args) {
        List<Integer> list60 = addArrayListSize(60);
        List<Integer> list600 = addArrayListSize(600);
        List<Integer> list6000 = addArrayListSize(6000);
        List<Integer> list60000 = addArrayListSize(60000);
        List<Integer> list600000 = addArrayListSize(600000);
        List<Integer> list6000000 = addArrayListSize(6000000);
        List<Integer> list60000000 = addArrayListSize(60000000);


        selectSize(list60);
        selectSize(list600);
        selectSize(list6000);
        selectSize(list60000);
        selectSize(list600000);
        selectSize(list6000000);
        selectSize(list60000000);
    }

    /**
     * 输出结果
     *
     * @param list
     */
    public static void selectSize(List<Integer> list) {
        System.out.println("==============" + list.size() + "次数==============");
        System.out.println("时间花费最少的是:  " + selectTraverse(list));
    }

    /**
     * 比较时间差
     *
     * @param list
     * @return 返回时间差最小的
     */
    public static String selectTraverse(List<Integer> list) {
        Long beforeTime1, beforeTime2, beforeTime3, beforeTime4, afterTime1, afterTime2, afterTime3, afterTime4;
        Long time1 = 0l;
        Long time2 = 0l;
        Long time3 = 0l;
        Long time4 = 0l;
        int j = 0;
        String result;
        Long minTime = 10000000000000000l;

        beforeTime1 = System.nanoTime();
        forTraverse(list);
        afterTime1 = System.nanoTime();
        time1 = afterTime1 - beforeTime1;
        System.out.println("forTraverse:" + time1 / 1000 + "微秒");

        beforeTime2 = System.nanoTime();
        enhanceForTraverse(list);
        afterTime2 = System.nanoTime();
        time2 = afterTime2 - beforeTime2;
        System.out.println("enhanceForTraverse:" + time2 / 1000 + "微秒");

        beforeTime3 = System.nanoTime();
        iteratorTraverse(list);
        afterTime3 = System.nanoTime();
        time3 = afterTime3 - beforeTime3;
        System.out.println("iteratorTraverse:" + time3 / 1000 + "微秒");

        beforeTime4 = System.nanoTime();
        forEachAddLambdaTraverse(list);
        afterTime4 = System.nanoTime();
        time4 = afterTime4 - beforeTime4;
        System.out.println("forEachAddLambdaTraverse:" + time4 / 1000 + "微秒");

        Long[] minTimeArray = {time1, time2, time3, time4};
        for (int i = 0; i < minTimeArray.length; i++) {
            if (minTimeArray[i] < minTime) {
                minTime = minTimeArray[i];
                j = i;
            }
        }
        if (j == 0) {
            result = "for循环遍历:" + minTime / 1000 + "微秒";
        } else if (j == 1) {
            result = "增强for循环遍历:" + minTime / 1000 + "微秒";
        } else if (j == 2) {
            result = "Iterator循环遍历:" + minTime / 1000 + "微秒";
        } else {
            result = "forEach循环遍历:" + minTime / 1000 + "微秒";
        }
        return result;
    }

    /**
     * 创建长度为size大小的ArrayList
     *
     * @param size
     * @return
     */
    public static List addArrayListSize(int size) {
        List<Integer> list = new ArrayList<Integer>();
        for (int i = 0; i < size; i++) {
            list.add(i);
        }
        return list;
    }

    /**
     * 使用for循环遍历ArrayList
     * @param list
     */
    public static void forTraverse(List<Integer> list) {
        for (int i = 0; i < list.size(); i++) {
            list.get(i).hashCode();
        }
    }

    /**
     * 增强的for循环遍历ArrayList
     * @param list
     */
    public static void enhanceForTraverse(List<Integer> list) {
        for (Integer integer : list) {
            integer.hashCode();
        }
    }

    /**
     * 使用Iterator迭代器对ArrayList进行遍历
     * @param list
     */
    public static void iteratorTraverse(List<Integer> list) {
        Iterator<Integer> iterator = list.iterator();
        while (iterator.hasNext()) {
            iterator.next().hashCode();
        }
    }

    /**
     * 使用forEach进行遍历
     * @param list
     */
    public static void forEachAddLambdaTraverse(List<Integer> list) {
        list.forEach(p -> {
            p.hashCode();
        });
    }
}

结果

==============60次数==============
forTraverse:37微秒
enhanceForTraverse:114微秒
iteratorTraverse:31微秒
forEachAddLambdaTraverse:53783微秒
时间花费最少的是:  Iterator循环遍历:31微秒
==============600次数==============
forTraverse:169微秒
enhanceForTraverse:183微秒
iteratorTraverse:134微秒
forEachAddLambdaTraverse:128微秒
时间花费最少的是:  forEach循环遍历:128微秒
==============6000次数==============
forTraverse:820微秒
enhanceForTraverse:693微秒
iteratorTraverse:629微秒
forEachAddLambdaTraverse:339微秒
时间花费最少的是:  forEach循环遍历:339微秒
==============60000次数==============
forTraverse:4765微秒
enhanceForTraverse:4958微秒
iteratorTraverse:4187微秒
forEachAddLambdaTraverse:2224微秒
时间花费最少的是:  forEach循环遍历:2224微秒
==============600000次数==============
forTraverse:4837微秒
enhanceForTraverse:7278微秒
iteratorTraverse:7538微秒
forEachAddLambdaTraverse:6408微秒
时间花费最少的是:  for循环遍历:4837微秒
==============6000000次数==============
forTraverse:13340微秒
enhanceForTraverse:15073微秒
iteratorTraverse:11847微秒
forEachAddLambdaTraverse:11261微秒
时间花费最少的是:  forEach循环遍历:11261微秒
==============60000000次数==============
forTraverse:129913微秒
enhanceForTraverse:105620微秒
iteratorTraverse:101002微秒
forEachAddLambdaTraverse:103978微秒
时间花费最少的是:  Iterator循环遍历:101002微秒

可以发现,在遍历不同次数的情况下,遍历的效率高低并不唯一,但从整体上来看,forEach遍历的效率确实是要高于其他。

总结

  • 可以看出4种遍历方式性能差距并不是很大,但从总体上看,forEach遍历的效率大概率上要高于其他三种。
  • 因为4种遍历方式性能都差不多,所以个人推荐使用方式为:按照个人习惯去使用。
  • 考虑到遍历越界,还是不推荐使用普通的for循环来遍历ArrayList
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值