• 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需要对中间插入元素后面的所有元素进行后移一位的操作)

    另外:

  • 相关阅读:
    如何通过命令行窗口查看sqlite数据库文件
    eclipse自动补全的设置
    文本装饰
    注释和特殊符号
    文本装饰
    网页背景
    通过ArcGIS Server admin 查看和删除已注册的 Web Adaptor
    通过 ArcGIS Server Manager 查看已安装的 Web Adaptor
    通过 ArcGIS Server Manager 验证 DataStore
    Windows上安装ArcGIS Enterprise——以 Windows Server 2012 R2上安装 ArcGIS 10.8为例
  • 原文地址:https://www.cnblogs.com/qilong853/p/6489508.html
Copyright © 2020-2023  润新知