LinkedList源码阅读

        LinkedList类继承自AbstractSequentialList类,并且实现了List, Deque Cloneable, java.io.Serializable接口,因此,LinkedList不仅可以作为单列集合来使用(适合应用于频繁修改集合内容、多写少读的场景),还可以作为队列(双端队列,因为它实现的是Deque接口)、栈来使用,此外LinkedList还可以被克隆和序列化传输。

public class LinkedList<E>
    extends AbstractSequentialList<E>
    implements List<E>, Deque<E>, Cloneable, java.io.Serializable

        由于LinkedList的底层实现结构是双向链表,因此它定义了两个Node对象——头节点和尾节点,并且使用size变量来记录双向链表的长度。

transient int size = 0;

transient Node<E> first;

transient Node<E> last;

        在LinkedList源码中,除了一些有关结构的定义也定义了很多方法,包括一些通用的常用方法以及针对具体的实现对象而创建的一些方法。

常用方法
方法名参数列表返回值类型作用
add()E eboolean向链表中添加元素(默认添加在尾节点后)
add()int index, E element向链表中的指定位置添加元素
addFirst()E e向链表的头部添加元素
addLast()E e向链表的尾部添加元素
addAll()Collection<? extends E> cboolean将一个单列集合中的所有元素添加到链表中
addAll()int index, Collection<? extends E> cboolean将一个单列集合中的所有元素添加到链表的指定位置中
get()int indexE(泛型)获取链表中指定下标的元素
getFirst()E获取链表中的头元素
getLast()E获取链表中的尾元素
indexOf()Object oint查找链表中指定下标元素的位置,如果不存在则返回-1
remove()E删除列表中的元素(默认删除头元素)
remove()Object oboolean删除指定内容的元素
remove()int indexE删除指定位置的元素
removeFirst()E删除链表的头元素
removeLast()E删除链表的尾元素
clear()清空列表中的所有元素
size()int获取链表的长度
sort()Comparator c(默认方法)根据Comparator比较器对列表元素进行排序
toArray()T[] aT[] (泛型数组)将链表转换成数组

由于LinkedList中的方法繁多,但实现结果类似,因此我将对部分方法的代码逻辑表述我的理解。

1.增添元素

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


void linkLast(E e) {
    //  获取当前的尾节点存放在l中
        final Node<E> l = last;
    //  把新节点e作为当前节点
        final Node<E> newNode = new Node<>(l, e, null);
        last = newNode;
    //  如果原尾节点为空,则表示链表为空,新的尾节点也是头节点
        if (l == null)
            first = newNode;
    //  如果原尾节点不为空,即链表不为空,则e为新的尾节点
        else
            l.next = newNode;
    // 链表长度加一
        size++;
        modCount++;
    }

 2.删除元素

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) {
        //定义了当前节点以及当前节点的上一个节点和下一个节点
        // assert x != null;
        final E element = x.item;
        final Node<E> next = x.next;
        final Node<E> prev = x.prev;
        
        //若当前节点的上一个节点为null,则设当前节点的下一个节点为头节点
        if (prev == null) {
            first = next;
        //若不为null,则当前节点为下一个节点,当前节点的上一个节点设为null
        } else {
            prev.next = next;
            x.prev = null;
        }
        //若当前节点的下一个节点为null,即当前节点为尾节点,则设当前节点的上一个节点为尾节点
        if (next == null) {
            last = prev;
        //否则,当前节点为上一个节点,他的下一个节点为null
        } else {
            next.prev = prev;
            x.next = null;
        }
        //x为null,链表长度减一,返回要素element
        x.item = null;
        size--;
        modCount++;
        return element;
    }

3.查找元素

        传入查找元素的下标,通过get()方法查询该位置的元素,在get()方法中调用了checkElementIndex()进行判别,如果下标范围< 0 或 >= size,则抛出索引越界异常。

public E get(int index) {
        checkElementIndex(index);
        return node(index).item;
    }


private void checkElementIndex(int index) {
        if (!isElementIndex(index))
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }


private boolean isElementIndex(int index) {
        return index >= 0 && index < size;
    }
作队列时的常用方法
方法名参数列表返回值类型作用
offer()E eboolean向队列中添加元素(默认添加在尾部)
offerFirst()E eboolean向队列的首部添加元素
offerLast()E eboolean向队列的尾部添加元素
poll()E删除队列中的元素(默认删除队头元素)
pollFirst()E删除队头元素
pollLast()E删除队尾元素
peek()E获取队头元素

1.删除元素

public E poll() {
        //将头节点存放在f节点
        final Node<E> f = first;
        //如果f为null,则返回null 如果不为null则调用unlinkFirst()方法
        return (f == null) ? null : unlinkFirst(f);
    }


private E unlinkFirst(Node<E> f) {
        // assert f == first && f != null;
        final E element = f.item;
        final Node<E> next = f.next;
        f.item = null;
        f.next = null; // help GC
        first = next;
        if (next == null)
            last = null;
        else
            next.prev = null;
        size--;
        modCount++;
        return element;
    }

2.获取元素

public E peek() {
        final Node<E> f = first;
        return (f == null) ? null : f.item;
    }
作为栈的常用方法
方法名参数列表返回值类型作用
push()E e进栈
pop()E栈顶元素出栈

1.入栈

public void push(E e) {
        addFirst(e);
    }

2.出栈 

public E pop() {
        return removeFirst();
    }

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值