ArrayList哪种循环效率更好你真的清楚吗

2020-04-28  本文已影响0人  java金融

ArrayList简介

声明:以下内容都是基于jdk1.8的

ArrayList数据结构

ArrayList包含了两个重要的对象:elementData 和 size。

ArrayList遍历方式

     // 随机访问
     List<String> list = new ArrayList<>();
     int size = list.size();
     for (int i = 0; i < size; i++) {
         value = list.get(i);
     }
     // 增强for循环
    for (String s : list) {
        value = s;
    }
     // 迭代器遍历
    Iterator<String> iter = list.iterator();
    while (iter.hasNext()) {
        value = iter.next();
    }
     list.forEach(p -> {
                p.hashCode();
            });

既然有4种遍历,那我们看看哪种遍历效率下面我们通过一个实验来看下这四种循环的耗时吧:
测试代码

/**
 * @Date: 2020/4/23 
 * @Description:
 */
public class ArrayListTest {
    public static void main(String[] args) {
        // 数据预热
       /* List<String> testList = createTestList(10);
        testForEach(testList);
        testFor(testList);
        testRandFor(10,testList);*/
        List<Integer> integers = Arrays.asList(10, 50, 100,500,1000, 10000, 50000, 100000, 5000000, 10000000,30000000);
        for (Integer i : integers) {
            testRand(i);
        }

    }

    private static void testRand(int size) {
        System.out.println("-----------次数:" + size + "------------");
        List<String> list = createTestList(size);
        // 随机访问通过索引值去遍历。
        long time1 = System.nanoTime();
        testRandFor(size, list);
        long time2 = System.nanoTime();
        // 增强for循环
        testFor(list);
        long time3 = System.nanoTime();
        // 迭代器遍历
        testIterator(list);
        long time4 = System.nanoTime();
        // forEach + lambda
        testForEach(list);
        long time5 = System.nanoTime();

        System.out.println("随机访问\t\t" + (time2 - time1) / 1000 + " ms");
        System.out.println("增强for遍历\t\t" + (time3 - time2) / 1000 + " ms");
        System.out.println("迭代器遍历\t\t" + (time4 - time3) / 1000 + " ms");
        System.out.println("forEach遍历\t\t" + (time5 - time4) / 1000 + " ms");
        System.out.println();
    }

    private static void testRandFor(int size, List<String> list) {
        for (int i = 0; i < size; i++) {
            list.get(i).hashCode();
        }
    }

    private static void testFor(List<String> list) {
        for (String s : list) {
            s.hashCode();
        }
    }

    private static void testIterator(List<String> list) {
        Iterator<String> iter = list.iterator();
        while (iter.hasNext()) {
            iter.next().hashCode();
        }
    }

    private static void testForEach(List<String> list) {
        list.forEach(p -> {
            p.hashCode();
        });
    }

    public static List<String> createTestList(int size) {
        List<String> list = new ArrayList<>(size);
        for (int i = 0; i < size; i++) {
            list.add(UUID.randomUUID().toString());
        }
        return list;
    }
}

测试数据结果如下:

-----------次数:10------------
随机访问        8 ms
增强for遍历     5 ms
迭代器遍历       2 ms
forEach遍历       40358 ms

-----------次数:50------------
随机访问        4 ms
增强for遍历     8 ms
迭代器遍历       7 ms
forEach遍历       5 ms

-----------次数:100------------
随机访问        13 ms
增强for遍历     18 ms
迭代器遍历       14 ms
forEach遍历       10 ms

-----------次数:500------------
随机访问        54 ms
增强for遍历     28 ms
迭代器遍历       24 ms
forEach遍历       57 ms

-----------次数:1000------------
随机访问        106 ms
增强for遍历     56 ms
迭代器遍历       50 ms
forEach遍历       37 ms

-----------次数:10000------------
随机访问        1192 ms
增强for遍历     892 ms
迭代器遍历       861 ms
forEach遍历       594 ms

-----------次数:50000------------
随机访问        3651 ms
增强for遍历     2908 ms
迭代器遍历       2563 ms
forEach遍历       2712 ms

-----------次数:100000------------
随机访问        10693 ms
增强for遍历     5273 ms
迭代器遍历       9294 ms
forEach遍历       3638 ms

-----------次数:5000000------------
随机访问        238922 ms
增强for遍历     29914 ms
迭代器遍历       30533 ms
forEach遍历       28016 ms

-----------次数:10000000------------
随机访问        431047 ms
增强for遍历     47151 ms
迭代器遍历       46371 ms
forEach遍历       38943 ms

-----------次数:30000000------------
随机访问        1163935 ms
增强for遍历     137710 ms
迭代器遍历       139211 ms
forEach遍历       129960 ms

ArrayList删除数据

虽然有四种遍历方式,但是能够正确删除数据的方式只有两种

 Iterator<String> iter = list.iterator();
        while (iter.hasNext()) {
            iter.next().hashCode();
            iter.remove();
        }
  for(int i = list.size()-1;i>=0;i--){
            list.remove(i);
        }

下面再演示下错误的删除操作

        List<String> list = new ArrayList<>();
        list.add("1");
        list.add("1");
        list.add("2");
        for(int i=0;i<list.size();i++){
           list.remove(i);
        }
        System.out.println(String.join(",",list));

结果输出:1

ArryList注意点

   List<String> list = new ArrayList<>();
        list.add("1");
        list.add("1");
        list.add("2");
        List<String> subList =  list.subList(0, 1);
        // 对原List增加一个值
        list.add("10");
        subList.add("11"); // 这一行会报 java.util.ConcurrentModificationException

上一篇下一篇

猜你喜欢

热点阅读