吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 3644|回复: 6
收起左侧

[Java 转载] Java的LinkedList源码(一)

[复制链接]
NullPointer 发表于 2016-12-2 11:13
只贴出了一部分源码,并不是所有方法的源码,后续更新get和addAll,大部分代码现在已贴出,如有不对的地方还请指正。
package collection;

import java.util.AbstractSequentialList;
import java.util.Collection;
import java.util.ConcurrentModificationException;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.NoSuchElementException;
import java.util.Queue;

public class LinkedList<E>
    extends AbstractSequentialList<E>
    implements List<E>, Deque<E>, Cloneable, java.io.Serializable
{
    /**
     * LinkedList的长度
     * transient:只能用来修饰字段,在对象序列化的过程中,带有此修饰符修饰的字段是不会被序列化的
     * 例如:User类有userName和transient password,那么序列化User类的时候password是不会被序列化的,
     * 所以反序列化拿出password也是null
     */
    transient int size = 0;

    /**
     * 指针头部
     */
    transient Node<E> first;

    /**
     * 指针尾部
     */
    transient Node<E> last;

    /**
     * 空构造器
     */
    public LinkedList() {
    }

    /**
     * 在链表头部插入元素
     */
    private void linkFirst(E e) {
            //先保存当前头节点
        final Node<E> f = first;
        //创建一个新节点,此新节点的上一个节点为null,下一个节点为当前头节点
        final Node<E> newNode = new Node<>(null, e, f);
        //让first指向新节点(更新头节点,这样可以保证对链表进行更改操作时first永远是第一个节点)
        first = newNode;
        //如果链表为null,则将last指向这唯一的新节点
        if (f == null)
            last = newNode;
        else //如果链表不为null,则将链表原来头节点的上一个元素指向新节点
            f.prev = newNode;
        size++;
        modCount++;
    }

    /**
     * 在链表尾部添加元素
     */
    void linkLast(E e) {
            //先保存当前尾节点
        final Node<E> l = last;
        //创建新节点,新节点的前驱(上一个节点)为当前尾节点,后驱为null
        final Node<E> newNode = new Node<>(l, e, null);
        //将链表尾节点指向新节点(更新尾节点,这样可以保证对链表进行更改操作时last永远是最后一个节点)
        last = newNode;
        //如果链表尾节点(指向新节点之前)为null,则将链表头节点指向新节点
        if (l == null)
            first = newNode;
        else //否则将链表尾节点(指向新节点之前)的上下一个节点指向新节点
            l.next = newNode;
        size++;
        modCount++;
    }

    /**
     * 向链表中间插入元素
     */
    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);
        succ.prev = newNode;
        if (pred == null)
            first = newNode;
        else
            pred.next = newNode;
        size++;
        modCount++;
    }

    /**
     * 移除链表头元素, f:链表头元素,从其他方法调用传参而来
     * f不可为null,调用此方法的地方都已判断
     */
    private E unlinkFirst(Node<E> f) {
        // assert f == first && f != null;
            //将element指向链表头节点的元素值
        final E element = f.item;
        //将next指向链表头节点的下一个节点
        final Node<E> next = f.next;
        //将链表头节点赋值为null
        f.item = null;
        //将链表头节点的下一个节点指向为null,有助于GC回收
        f.next = null; // help GC
        //将链表头节点first指向为next(目的是为了数据的正确性,删除此元素,要保证first指向下一个元素,不能指向当前删除的这个)
        first = next;
        //如果链表只有1个元素,则将last指向null,变成空链表
        if (next == null)
            last = null;
        else //否则将链表的上一个元素指向null
            next.prev = null;
        //长度减1
        size--;
        modCount++;
        //返回被移除的元素
        return element;
    }

    /**
     * 移除链表尾元素, l:链表尾元素,从其他方法调用传参而来
     * l不可为null,调用此方法的地方都已判断
     */
    private E unlinkLast(Node<E> l) {
        // assert l == last && l != null;
            //将链表尾节点的元素值赋给element
        final E element = l.item;
        //找到链表尾节点的上一个节点
        final Node<E> prev = l.prev;
        l.item = null;
        l.prev = null; // help GC
        //last指向前一个元素
        last = prev;
        //若前一个元素为null,则证明链表只有l这一个元素,则将first设置为null,变成空链表
        if (prev == null)
            first = null;
        else //否则删除此元素
            prev.next = null;
        size--;
        modCount++;
        //返回删除的这个元素
        return element;
    }

    /**
     * 从链表中间删除节点
     */
    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;

        //前驱为空,说明删除的是头节点,first要指向下一个节点
        if (prev == null) {
            first = next;
        } else { //否则前驱节点的后继节点变为当前删除节点的下一个节点
            prev.next = next;
            x.prev = null;
        }
        //后驱为空,说明删除的是尾节点,last要指向前一个节点
        if (next == null) {
            last = prev;
        } else { //否则后驱节点的上一个节点变为当前删除的上一个节点
            next.prev = prev;
            x.next = null;
        }
        //将此元素设置为null
        x.item = null;
        size--;
        modCount++;
        //返回删除的元素
        return element;
    }

    /**
     * 获取链表第一个节点
     */
    public E getFirst() {
            //将节点f指向链表头节点
        final Node<E> f = first;
        //如果链表头节点为null,则抛出没有此元素的异常,否则返回此元素
        if (f == null)
            throw new NoSuchElementException();
        return f.item;
    }

    /**
     * 获取链表最后一个节点
     */
    public E getLast() {
            //将节点l指向链表尾节点
        final Node<E> l = last;
        //如果链表尾节点为null,则抛出没有此元素的异常,否则返回此元素
        if (l == null)
            throw new NoSuchElementException();
        return l.item;
    }

    /**
     * 移除链表头节点
     */
    public E removeFirst() {
            //将节点f指向链表头节点
        final Node<E> f = first;
        //如果链表头节点为null,则抛出没有此元素的异常,否则移除此元素,并返回移除的元素
        if (f == null)
            throw new NoSuchElementException();
        return unlinkFirst(f);
    }

    /**
     * 移除链表尾节点
     */
    public E removeLast() {
            //将节点f指向链表尾节点
        final Node<E> l = last;
        //如果链表尾节点为null,则抛出没有此元素的异常,否则移除此元素,并返回移除的元素
        if (l == null)
            throw new NoSuchElementException();
        return unlinkLast(l);
    }

    /**
     * 向链表头部插入节点
     */
    public void addFirst(E e) {
        linkFirst(e);
    }

    /**
     * 向链表尾部插入节点
     */
    public void addLast(E e) {
        linkLast(e);
    }

    /**
     * 判断元素是否在链表中。true:在。false:不在
     */
    public boolean contains(Object o) {
        return indexOf(o) != -1;
    }

    /**
     * 返回链表长度
     */
    public int size() {
        return size;
    }

    /**
     * 向链表尾部插入元素,成功则返回true
     */
    public boolean add(E e) {
        linkLast(e);
        return true;
    }

    /**
     * 移除链表中的某元素,true:成功,false:失败
     */
    public boolean remove(Object o) {
        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;
    }


    /**
     * 返回元素在链表中第一次出现的位置下标,若不存在,则返回-1
     */
    public int indexOf(Object o) {
        int index = 0;
        if (o == null) {//当元素为null时,防止空指针,null用等于判断,非null的字符串用equals
                //遍历
            for (Node<E> x = first; x != null; x = x.next) {
                //链表节点元素中存在null,则返回位置
                if (x.item == null)
                    return index;
                index++;
            }
        } else { //当元素不为null时
            for (Node<E> x = first; x != null; x = x.next) {
                if (o.equals(x.item))
                    return index;
                index++;
            }
        }
        return -1;
    }

    /**
     * 返回元素在链表中最后一次出现的位置下标,若不存在,则返回-1
     */
    public int lastIndexOf(Object o) {
        int index = size;
        if (o == null) {
            for (Node<E> x = last; x != null; x = x.prev) {
                index--;
                if (x.item == null)
                    return index;
            }
        } else {
            for (Node<E> x = last; x != null; x = x.prev) {
                index--;
                if (o.equals(x.item))
                    return index;
            }
        }
        return -1;
    }

    /*
     * 链表上的每个节点
     */
    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;
        }
    }

}


免费评分

参与人数 2热心值 +2 收起 理由
Titanic + 1 谢谢@Thanks!虽然还没有学到,才学到ArrayList和HashMap
n257259 + 1 热心回复!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

小阿小叮当 发表于 2016-12-2 11:34
膜拜大神
江南5753 发表于 2016-12-2 11:56
xj1124 发表于 2016-12-2 12:01
Vvvvvoid 发表于 2016-12-2 12:06
Eclipse
Ctrl + 左键啊
While_Shark 发表于 2016-12-2 12:15
好的,多谢楼主
 楼主| NullPointer 发表于 2016-12-2 12:48
江南5753 发表于 2016-12-2 11:56
这个厉害,还有二?

这个不全,只是写了常用的,可以看出来LinkedList移动元素很方便,效率很高,但是我并没有写get的,get的效率很低下了,打算在后续文章中写出,并与之前写的ArrayList的做对比。
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-15 13:37

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表