LinkedList是常用的一种List的实现类,采取单向链表的结构


在LinkedList中,以一个内部的Node类来代表集合中的对象,对象的值赋给item属性,Node中的next属性指向当前对象的后一个对象,prev属性指向对象的前一个对象。同时也用了两个node属性,一个first代表链表的第一个元素


一个last代表链表的末尾,LinkedList具体实现方法如下:



一.LinedList继承结构


java.lang.Object
       -java.util.AbstractCollection<E>
            -java.util.AbstractList<E>
                 -java.util.AbstractSequentialList<E>
                      -java.util.LinkedList<E>



实现的接口:List<E>, Deque<E>, Cloneable, Serializable


二.实现方法介绍:


2.1 构造方法


~LinkedList() 默认构造器,创建一个空的list


~LinkedList(Collection<? extends E> c) 创建一个list,里面包含指定集合中的所有元素


2.2 add 插入对象



~void addFirst(E e) 在开头添加元素

~void addLast(E e) 在末尾添加元素

~void add(E element) 在末尾添加指定的元素

~void add(int index, E element) 在指定的索引位置,增加指定的元素

~public boolean addAll(Collection<? extends E> c) 插入集合中的所有对象

~public boolean addAll(int index, Collection<? extends E> c) 在指定位置插入集合中的对象


源码分析:


public boolean add(E e) {
       linkLast(e);
       return true ;
 }


往list末尾添加一个对象


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++;
    }


获取末尾对象,创建一个新的node对象,node的prev指向末尾元素,如果末尾为空,即这个list中还未添加对象,则将first指向newNode,否则添加到末尾。


LinkedList的add方法不用考虑像arrayList一样进行扩容和复制数据的问题,但是每增加一个数据,都需要创建一个新的Node<E> 对象

2.3 remove 删除对象

~E removeFirst() 删除链表的第一个对象,返回删除的对象

~E removeLast() 删除链表的最后一个对象

~boolean remove(Object o)  删除指定的对象

~E remove(int index) 删除指定位置的对象

~E remove() 调用removeFirst


public boolean remove(Object o) {
          //判断删除的对象是否为null
        if (o == null ) {
            for (Node<E> x = first ; x != null; x = x.next) {
                if (x.item == null) {
                    unlink(x);
                    return true ;
                }
            }
        } else {
            //循环遍历找到指定的对象
            for (Node<E> x = first ; x != null; x = x.next) {
                if (o.equals(x.item )) {
                    unlink(x);
                    return true ;
                }
            }
        }
        return false ;
    }



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 = next;
        } else {
            //把x从链表中去掉
            prev. next = next;
            x. prev = null;
        }

        if (next == null) {
            last = prev;
        } else {
            next. prev = prev;
            x. next = null;
        }
        //x的属性都赋值为空,让GC处理掉
        x. item = null;
        size--;
        modCount++;
        return element;
    }


LinkedList删除元素比ArrayList简单很多,毕竟ArrayList将当前元素所在位置后的元素通过复制往前移动一位

2.4 get 获取对象

~E get(int index) 获取指定位置的元素

~E getFirst() 获取首元素

~E getLast() 获取末尾元素

源码分析:


public E get (int index) {
         //入参检验
        checkElementIndex(index);
        return node(index).item ;
    }
Node<E> node (int index) {
         // 判断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的元素是存放到链表里面的,所以get操作相对ArrayList来说要复杂一些


2.5 contains 判断集合中是否存在这个元素


~boolean contains(Object o)


三.LinkedList总结

~jdk1.7 中的linkedList采用单向链表的方式实现

~LinkedList在插入元素的时候需要创建一个新的node对象,在查找元素的时候需要遍历链表,在删除元素的时候,要遍历链表,找到指定的元素进行删除

~LinkedList是非线程安全的