• LinkedList的一种错误使用方法


    近期在做图像处理的时候。发现某一段代码很的慢。慢得让人无法接受。基本的代码是顺序訪问一个LinkedList的元素,效果是随着index的变大,速度越来越慢,list的元素个数在百万以上。找到原因,分享出来。也希望大家不要跳入同一个陷阱。

    还是那一句话。可执行的代码和高质量的代码之间还是有比較远的距离。

    LinkedList错误使用方法演示样例

    代码里面增加了一些打印时间相关的代码,主要是为了直观的显示执行的耗时。

    错误代码

    public static void main(String[] args) {
        // add elements
        int size = 2000000;
        List<String> list = new LinkedList<String>();
        for (int i = 0; i < size; i++) {
            list.add("Just some test data");
        }
    
        long startTime = System.currentTimeMillis();
        for (int i = 0; i < size; i++) {
            list.get(i);
    
            if (i % 10000 == 0) {
                System.out.println("query 10000 elements spend: "
                        + (System.currentTimeMillis() - startTime));
                startTime = System.currentTimeMillis();
            }
        }
    }
    

    控制台输出例如以下:


    错误原因

    错误的代码就是list.get(i),LinkedList的底层是一个链表,随机訪问i的时候。链表仅仅能从头往后数,第i个才返回。所以时间随着i的变大时间会越来越长。

    正确使用方法

    顺序訪问,LinkedList绝对不要用get方法,即使LinkedList的元素个数仅仅有非常少的几个。

    养成好习惯,免得犯错。

    for each

    for (String element : list) {
        // process element here
    }
    

    iterator

    Iterator<String> iter = list.iterator();
    while (iter.hasNext()) {
        String element = iter.next();
        // process element here
    }
    

    直接换为ArrayList

    public static void main(String[] args) {
        // add elements
        int size = 2000000;
        List<String> list = new ArrayList<String>();
        for (int i = 0; i < size; i++) {
            list.add("Just some test data");
        }
    
        long startTime = System.currentTimeMillis();
        for (int i = 0; i < size; i++) {
            list.get(i);
    
            if (i % 10000 == 0) {
                System.out.println("query 10000 elements spend: "
                        + (System.currentTimeMillis() - startTime));
                startTime = System.currentTimeMillis();
            }
        }
    }
    

    ArrayList的控制台输出例如以下:


    LinkedList VS ArrayList

    以下比較一下LinkedList和ArrayList的效率。

    新增、查询、删除比較

    ArrayList測试代码例如以下:

    public static void main(String[] args) {
        // add elements
        int size = 20000000;
        List<String> list = new ArrayList<String>();
        long startTime = System.currentTimeMillis();
        for (int i = 0; i < size; i++) {
            list.add("Just some test data");
        }
        System.out.println("add " + size + " elements spend: "
                + (System.currentTimeMillis() - startTime));
    
        // query
        startTime = System.currentTimeMillis();
        String median = list.get(size / 2);
        System.out.println("query median spend: "
                + (System.currentTimeMillis() - startTime));
    
        // delete
        startTime = System.currentTimeMillis();
        list.remove(median);
        System.out.println("delete median spend: "
                + (System.currentTimeMillis() - startTime));
    }
    

    LinkedList測试代码例如以下:

    public static void main(String[] args) {
        // add elements
        int size = 20000000;
        List<String> list = new LinkedList<String>();
        long startTime = System.currentTimeMillis();
        for (int i = 0; i < size; i++) {
            list.add("Just some test data");
        }
        System.out.println("add " + size + " elements spend: "
                + (System.currentTimeMillis() - startTime));
    
        // query
        startTime = System.currentTimeMillis();
        String median = list.get(size / 2);
        System.out.println("query median spend: "
                + (System.currentTimeMillis() - startTime));
    
        // delete
        startTime = System.currentTimeMillis();
        list.remove(median);
        System.out.println("delete median spend: "
                + (System.currentTimeMillis() - startTime));
    }
    

    各自特点

    • 新增
      ArrayList比LinkedList快非常多,超过一个数量级。

      非常是意外。

    • 随机查询
      在i值非常大的时候,ArrayList比LinkedList快非常多,i越大,差距越大。ArrayList底层是数组。随机訪问时间效率是O(0),而LinkedList是O(n)。

    • 删除
      LinkedList比ArrayList快非常多。LinkedList的删除操作时间效率为O(0)。而ArrayList是O(n),ArrayList须要查找数据、移动数据,所以慢。

    总结

    尽量使用ArrayList,ArrayList满足不了需求的时候再用LinkedList。依据LinkedList的特点,在以下几种情况下才使用LinkedList。

    • 须要使用java.util.List接口之外的API
      LinkedList实现了Queue和Stack等接口,能够用来当作一些特殊的容器。吐槽JDK里面LinkedList的设计,塞太多东西了,和名字不符。
    • 元素删除比較频繁
      假设数据量大,删除频繁,仅仅能用LinkedList。

    • 内存碎片化且元素非常多
      ArrayList底层是一个数组,数组要求一段连续的内存快。LinkedList也能够充分利用内存的一些碎片。特别是JVM使用Concurrent Mark-Sweep Collector垃圾回收器的时候,显得尤为重要。

  • 相关阅读:
    更新pip10后 ImportError: cannot import name ‘main'
    动态规划刷题集python代码
    ctr中的GBDT+LR的优点
    msgpack生成lib,vs新建lib等
    两个简单的动态规划问题,0-1背包和最大不相邻数累加和,附递归c代码
    贝叶斯先验解释l1正则和l2正则区别
    找出平面上斜率最大的两点
    Maven——快速入门手册(学习记录)
    Java基础——深入理解Java中的final关键字(转载)
    Spring——scope详解(转载)
  • 原文地址:https://www.cnblogs.com/claireyuancy/p/6738215.html
Copyright © 2020-2023  润新知