• ArrayList和LinkedList部分源码分析性能差异


    ArrayList底层为数组结构,add方法:

        public void add(int index, E element) {
            rangeCheckForAdd(index);
    
            ensureCapacityInternal(size + 1);  // Increments modCount!!
            System.arraycopy(elementData, index, elementData, index + 1,
                             size - index);//这是一个本地native方法
            elementData[index] = element;
            size++;
        }

    set方法:

    public E set(int index, E element) {
            rangeCheck(index);
    
            E oldValue = elementData(index);
            elementData[index] = element;
            return oldValue;
        }

    LinkedList底层为链表结构,set方法:

        public E set(int index, E element) {
            checkElementIndex(index);
            Node<E> x = node(index);
            E oldVal = x.item;
            x.item = element;
            return oldVal;
        }

    看一下Node:

     private static class Node<E> {
            E item;//本项元素
            Node<E> next;//下一个元素
            Node<E> prev;//前一个元素
    
            Node(Node<E> prev, E element, Node<E> next) {
                this.item = element;
                this.next = next;
                this.prev = prev;
            }
        }

    看一下node(index)方法是如何根据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;
            }
        }

    下面看一下LinkedList的add方法:

     public void add(int index, E element) {
            checkPositionIndex(index);//检查下标合法
    
            if (index == size)
                linkLast(element);//在末尾加元素
            else
                linkBefore(element, node(index));//在中间加元素
        }
    void linkLast(E e) {
            final Node<E> l = last;
            final Node<E> newNode = new Node<>(l, e, null);//构造新的最后Node节点,设置后一个元素为null
            last = newNode;
            if (l == null)//数组内没有元素
                first = newNode;
            else//设置前一个元素的后指向
                l.next = newNode;
            size++;
            modCount++;
        }
    linkLast方法比较简单,看一下linkBefore:
     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);//构造新的Node节点,设置前后指向
            succ.prev = newNode;//设置后一个元素的前指向
            if (pred == null)//设置前一个元素的后指向
                first = newNode;
            else
                pred.next = newNode;
            size++;
            modCount++;
        }

    因此:

    ArrayList在随机访问(get,set)方面更高效(直接根据下标就可找到元素,LinkedList需要从最前或者最后进行依次查找)

    LinkedList在List的中间插入和移除时更高效(LinkedList最多涉及三个元素的的更改,ArrayList需要对中间插入元素后面的所有元素进行后移一位的操作)

    另外:

  • 相关阅读:
    利用outlook发送邮件的代码,其实就一句话,哈哈~~
    一个或多个数据库无法访问,因而不会在数据库访问选项卡中显示
    窗口碰壁弹回的浮动广告代码
    DataFormatString格式化数据及格式化时间失效的问题
    弹出并转向代码
    常用运行命令
    post和get
    自己总结的手动生成gridview导出excel的方法
    Spring boot download file
    RESTful WebService 入门实例
  • 原文地址:https://www.cnblogs.com/qilong853/p/6489508.html
Copyright © 2020-2023  润新知