zoukankan      html  css  js  c++  java
  • LinkedList源码解析

    1、LinkedList的结构如下

    public class LinkedList<E>
        extends AbstractSequentialList<E>
        implements List<E>, Deque<E>, Cloneable, java.io.Serializable
    {
        transient int size = 0;
    
        //第一个节点
        transient Node<E> first;
    
        //最后一个节点
        transient Node<E> last;
    
        //节点的结构
        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;
            }
        }
    
    }
    

      由上面可知,LinkList是一个双向列表结构

    2、构造函数

        //空的构造函数
        public LinkedList() {
        }
    
        //传入集合的构造函数
        public LinkedList(Collection<? extends E> c) {
            this();
            addAll(c);
        }  

    和ArrayList对比可以发现,LinkedList没有容量的限制,不需要指定集合的大小。

    3、元素添加

        //1、添加单个元素。在最后一个元素后面添加
        public boolean add(E e) {
            linkLast(e);
            return true;
        }
        //2、添加元素到指定位置
        public void add(int index, E element) {
            checkPositionIndex(index);
    
            if (index == size)
                linkLast(element);
            else
                linkBefore(element, node(index));
        }
        //3、添加到头元素
        public void addFirst(E e) {
            linkFirst(e);
        }
        //4、添加到尾元素
        public void addLast(E e) {
            linkLast(e);
        }
        //5、添加到集合
        public boolean addAll(Collection<? extends E> c) {
            return addAll(size, c);
        }
    

     主要调用了linkFirst和linkLast这两个方法

    1) linkLast(E e)

        void linkLast(E e) {
            final Node<E> l = last;
            //1、创建一个Node,prev指向last,netx为空
            final Node<E> newNode = new Node<>(l, e, null);
            //2、last节点为新加的节点
            last = newNode;
            //3、如果last节点为空,则说明新增加的节点newNode是第一个元素。
    	//否则,将原来的last节点的next复制为新的节点
            if (l == null)
                first = newNode;
            else
                l.next = newNode;
            size++;
            modCount++;
        }
    

      

     4、删除操作

    删除操作,总结起来就是unlink方法

     E unlink(Node<E> x) {
            //获取当前节点的元素,前一个节点和后一个节点
            final E element = x.item;
            final Node<E> next = x.next;
            final Node<E> prev = x.prev;
            //如果要删除节点的前一个节点为空,则说明要删除的元素就是第一个元素。
            if (prev == null) {
    	    //将该元素的下一个节点赋值给first节点
                first = next;
            } else {
    	    //如果要删除节点的前一个节点不为空。则将他前一个节点的next赋值为当前节点的next
                prev.next = next;
                x.prev = null;
            }
    
    	//如果要删除的元素next为空,则说明要删除的元素是最后一个元素。
            if (next == null) {
                //将该元素的前一个节点赋值给last
                last = prev;
            } else {
                next.prev = prev;
                x.next = null;
            }
    	//将当前元素置为null
            x.item = null;
            size--;
            modCount++;
            return element;
        }
    

      

     5、修改元素

       public E set(int index, E element) {
            checkElementIndex(index);
    	//获取到当前元素
            Node<E> x = node(index);
    	//老的元素
            E oldVal = x.item;
    	//将新的元素赋值给x.item
            x.item = element;
            return oldVal;
        }
    

      

    6、查询元素

    1) 按index查询元素。(查询第几个元素)

        Node<E> node(int index) {
            //如果index在整个链表的前半部分,在从first往后查询
            if (index < (size >> 1)) {
                Node<E> x = first;
                for (int i = 0; i < index; i++)
                    x = x.next;
                return x;
            } 
    	//如果index在整个链表的后半部分,在从last往前查询
    	else {
                Node<E> x = last;
                for (int i = size - 1; i > index; i--)
                    x = x.prev;
                return x;
            }
        }
    

     

    2) 按照对象查询元素的位置(index) 

        public int indexOf(Object o) {
    	//从前往后遍历
            int index = 0;
            if (o == null) {
                for (Node<E> x = first; x != null; x = x.next) {
                    if (x.item == null)
                        return index;
                    index++;
                }
            } else {
                for (Node<E> x = first; x != null; x = x.next) {
                    if (o.equals(x.item))
                        return index;
                    index++;
                }
            }
            return -1;
        }
    

      

     ArrayList和LinkedList使用对比: Java ArrayList,LinkedList使用

  • 相关阅读:
    【串线篇】Mybatis缓存原理
    【串线篇】Mybatis之动态sql
    【串线篇】Mybatis之模糊查询
    【串线篇】sql映射文件-分布查询(上)association 1-1
    【串线篇】SQL映射文件-联合查询(完结association+cellection)
    【串线篇】加谈数据库之连接join
    【串线篇】数据库设计之加谈n-n
    【串线篇】SQL映射文件-resultMap自定义封装
    【串线篇】sql注入问题
    【串线篇】SQL映射文件select简单查询标签
  • 原文地址:https://www.cnblogs.com/linlf03/p/12621283.html
Copyright © 2011-2022 走看看