LinkedList插入数据效率不一定比ArrayList高,源码分析+实验对比

(一)结论

  1. 在尾部插入数据,数据量较小时LinkedList比较快,因为ArrayList要频繁扩容,当数据量大时ArrayList比较快,因为ArrayList扩容是当前容量*1.5,大容量扩容一次就能提供很多空间,当ArrayList不需扩容时效率明显比LinkedList高,因为直接数组元素赋值不需new Node

  2. 在首部插入数据,LinkedList较快,因为LinkedList遍历插入位置花费时间很小,而ArrayList需要将原数组所有元素进行一次System.arraycopy

  3. 插入位置越往中间,LinkedList效率越低,因为它遍历获取插入位置是从两头往中间搜,index越往中间遍历越久,因此ArrayList的插入效率可能会比LinkedList高

  4. 插入位置越往后,ArrayList效率越高,因为数组需要复制后移的数据少了,那么System.arraycopy就快了,因此在首部插入数据LinkedList效率比ArrayList高,尾部插入数据ArrayList效率比LinkedList高

  5. LinkedList可以实现队列,栈等数据结构,这是它的优势

(二)在尾部插入数据

结论:当数据量越来越大时,ArrayList比LinkedList快

原因:当数据量大时,ArrayList每次扩容都能得到很大的新空间,解决了前期频繁扩容的劣势,而LinkedList虽然有尾指针,但是每次add都要将对象new成一个Node(而ArrayList直接数组对应位置元素赋值)

末尾插入源码:

ArrayList:如果超出容量需要扩容,不需扩容时直接数组元素赋值

    public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }

LinkedList:用传入的值new一个Node对象,然后尾指针指向该新的Node

    public void addLast(E e) {
        linkLast(e);
    }
    void linkLast(E e) {
        final Node<E> l = last;
        final Node<E> newNode = new Node<>(l, e, null);
        last = newNode;
        if (l == null)
            first = newNode;
        else
            l.next = newNode;
        size++;
        modCount++;
    }

实验对比:

    public static void main(String[] argv) {
        LinkedList<Integer> linkedList = new LinkedList<Integer>();
        ArrayList<Integer> arrayList = new ArrayList<Integer>();
        Long start = System.nanoTime();
        for (int i = 0; i < 100000; i++) {
            linkedList.addLast(i);

        }
        Long end = System.nanoTime();
        System.out.println("LinkedList消耗时间:" + (end - start));

        start = System.nanoTime();
        for (int i = 0; i < 100000; i++) {
            arrayList.add(i);
        }
        end = System.nanoTime();
        System.out.println("ArrayList消耗时间:" + (end - start));
    }

(三)指定位置插入数据

(1)源码对比

ArrayList:性能主要在于扩容和数组复制,而当size很大时扩容影响就会减少

  1. 判断index是否合法
  2. 判断是否需要扩容
  3. 数组复制,从index开始把后面的数组元素全部复制到相对后一位的位置,该方法是native方法而且是连续内存复制问题,因此性能影响也没想象中的大
  4. 将element赋值给数组index元素
    public void add(int index, E element) {
        rangeCheckForAdd(index);

        ensureCapacityInternal(size + 1);  // Increments modCount!!
        System.arraycopy(elementData, index, elementData, index + 1,
                         size - index);
        elementData[index] = element;
        size++;
    }

LinkedList:性能主要在于遍历链表查找index

  1. 判断是否超过链表长度,超过则抛错误
  2. 如果是插入最后的位置直接使用linkLast方法而不必去遍历查询对应位置
  3. node方法寻找index所指向的Node,首先判断index是否大于size/2,大于则从末尾往前找,小于则从0开始往后找
  4. 找到之后就是new一个node对象,设置指针的问题
    public void add(int index, E element) {
        checkPositionIndex(index);

        if (index == size)
            linkLast(element);
        else
            linkBefore(element, node(index));
    }

    Node<E> node(int index) {
        // assert isElementIndex(index);

        if (index < (size >> 1)) {
            Node<E> x = first;
            for (int i = 0; i < index; i++)
                x = x.next;
            return x;
        } else {
            Node<E> x = last;
            for (int i = size - 1; i > index; i--)
                x = x.prev;
            return x;
        }
    }

    void linkBefore(E e, Node<E> succ) {
        // assert succ != null;
        final Node<E> pred = succ.prev;
        final Node<E> newNode = new Node<>(pred, e, succ);
        succ.prev = newNode;
        if (pred == null)
            first = newNode;
        else
            pred.next = newNode;
        size++;
        modCount++;
    }

(2)首部插入实验对比

结论:开头插入,LinkedList比ArrayList快

(2)中间插入实验对比

结论:中间插入LinkedList比ArrayList慢

原文地址:https://www.cnblogs.com/ming-szu/p/9533019.html

时间: 2024-11-08 09:37:49

LinkedList插入数据效率不一定比ArrayList高,源码分析+实验对比的相关文章

ArrayList部分源码分析(基于1.8)

今天分析第一个集合类:ArrayList 首先,说一下我读这部分源码的感受. ArrayList类底层实现实际上是数组,因此很多操作会调用很多本地(Native)方法来实现或者部分实现.用java实现的很多方法中,只是用java代码进行了一些必要的逻辑判断和变量值的改变. 在AbstractList中加入的modCount变量是为了配合迭代器的使用. 下面是部分源码分析: package java.util; import java.util.function.Consumer; import

LinkedList其实就那么一回事儿之源码分析

上篇文章<ArrayList其实就那么一回儿事儿之源码分析>,给大家谈了ArrayList, 那么本次,就给大家一起看看同为List 家族的LinkedList. 下面就直接看源码吧: public class LinkedList<E> extends AbstractSequentialList<E> implements List<E>, Deque<E>, Cloneable, java.io.Serializable { transie

Java——ArrayList底层源码分析

1.简介 ArrayList 是最常用的 List 实现类,内部是通过数组实现的,它允许对元素进行快速随机访问.数组的缺点是每个元素之间不能有间隔, 当数组大小不满足时需要增加存储能力,就要将已经有数组的数据复制到新的存储空间中. 当从 ArrayList 的中间位置插入或者删除元素时,需要对数组进行复制.移动.代价比较高.因此,它适合随机查找和遍历,不适合插入和删除. 线性表的顺序存储,插入删除元素的时间复杂度为O(n),求表长以及增加元素,取第 i 元素的时间复杂度为O(1). ArrayL

ArrayList&lt;E&gt;源码分析

ArrayList是按照线性表结构实现的 ArrayList的主要继承结构 public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable public interface List<E> extends Collection<E> public interface Collect

ArrayList的源码分析(基于jdk1.8)

1.初始化 transient Object[] elementData; //实际存储元素的数组 private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; public ArrayList() { //初始化为一个默认的空数组 this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; } 2. 添加元素 private static final int DEFAU

ArrayList的源码分析

/** Default initial capacity. 初始化容量为10 */private static final int DEFAULT_CAPACITY = 10;private static final Object[] EMPTY_ELEMENTDATA = {};/** Shared empty array instance used for default sized empty instances. We distinguish this from EMPTY_ELEMEN

Java集合源码分析之LinkedList

1. LinkedList简介 public class LinkedList<E> extends AbstractSequentialList<E> implements List<E>, Deque<E>, Cloneable, java.io.Serializable 可以看到LinkedList类继承AbstractSequentialList类,实现了List, Deque, Cloneable, java.io.Serializable接口.实

Java - LinkedList源码分析

java提高篇(二二)---LinkedList 一.概述 LinkedList与ArrayList一样实现List接口,只是ArrayList是List接口的大小可变数组的实现,LinkedList是List接口链表的实现.基于链表实现的方式使得LinkedList在插入和删除时更优于ArrayList,而随机访问则比ArrayList逊色些. LinkedList实现所有可选的列表操作,并允许所有的元素包括null. 除了实现 List 接口外,LinkedList 类还为在列表的开头及结尾

ArrayList、LinkedList和Vector源码分析

ArrayList.LinkedList和Vector源码分析 ArrayList ArrayList是一个底层使用数组来存储对象,但不是线程安全的集合类 ArrayList的类结构关系 public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable { } ArrayList实现了List接口,List