LinkedList底层源码

LinkedList
双向链表实现,增删快,查询慢 (线程不安全)

属性:
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;  指向上一个节点

        //创建节点对象的参数
          prev前一个节点的引用  element具体存储的数据   next下一个节点引用
        Node(Node<E> prev, E element, Node<E> next) {
            this.item = element;
            this.next = next;
            this.prev = prev;
        }
    }

构造器方法   
public LinkedList() {
    }
    
没有指定容积的构造器,理论上来说,链表实际上没有长度限制,但是int size属性要求元素个数必须在[0,Integer.max-value]范围内

add方法的定义:在双向链表的末尾新增元素
public boolean add(E e) {
        linkLast(e);
        return true;
    }
    
     void linkLast(E e) {
        final Node<E> l = last;  缓存尾节点
        final Node<E> newNode = new Node<>(l, e, null);  创建新的节点,新节点的下一个节点为null
        last = newNode;  将尾指针执行新创建的节点
        if (l == null)   如果原来的尾节点为null,则新增的节点应该是链表的第一个节点
            first = newNode;  将头指针指向新创建的节点
        else  
            l.next = newNode;  如果原来的尾节点不为null,则表示已经有元素了,将原来的尾节点指向新创建的节点,这样就将新节点加入到链表中
        size++; 链表中元素个数加1
        modCount++;  修改次数加1
    }
    
   --------------------------------------------------------------------------------

add(int,Object) 在指定位置新增元素,原来位置上的元素后移
public void add(int index, E element) {
        checkPositionIndex(index); 检查index的合法性,要求index应该是在[0,size]的范围内
            index >= 0 && index <= size;如果不合法则抛出异常IndexOutOfBoundsException
        if (index == size)  如果索引值index等于size,则在链表默认添加元素
            linkLast(element);
        else  在指定下标位置之前添加元素
            linkBefore(element, node(index));
    }
    
    //获取指定位置上的节点对象
    Node<E> node(int index) {
        if (index < (size >> 1)) { 如果序号值小于size/2则从头指针开始遍历链表,查找指定索引值的元素Node
            Node<E> x = first;
            for (int i = 0; i < index; i++)
                x = x.next;  从前向后遍历
            return x;
        } else { 如果序号值大于等于size/2则从尾指针开始遍历链表,查找指定索引值的元素Node
            Node<E> x = last;
            for (int i = size - 1; i > index; i--)
                x = x.prev;  从后向前遍历
            return x;
        }
    }

在指定节点对象之前添加e数据
void linkBefore(E e, Node<E> succ) {
        final Node<E> pred = succ.prev;  获取指定位置的前一个节点
        final Node<E> newNode = new Node<>(pred, e, succ);  创建节点对象,参数1是原始节点的前一个节点,参数2是具体存储的数据,参数3是原始位置上的节点
        succ.prev = newNode;  设置原始位置上的node对象的前一个节点为新创建的节点【双向链表】
        if (pred == null)  如果指定位置的节点的前一个节点为null,则插入的新节点应该就是头节点
            first = newNode;  使头指针指向新创建的节点
        else   设置前一个节点的下一个节点指针指向新创建的节点
            pred.next = newNode;
        size++;  元素个数加1
        modCount++;  修改次数加1
    }
    
   --------------------------------------------------------------------------------

删除和参数相等的第一个元素
删除成功返回true,否则返回false
    public boolean remove(Object o) {
        if (o == null) {  删除值为null的元素,使用==判断
            for (Node<E> x = first; x != null; x = x.next) {从头指针开始执行遍历,查找第一个值为null的节点
                if (x.item == null) {  //判断当前节点的值是否为null
                    unlink(x);  删除指定的Node节点,并且返回Node中存储的数据
                    return true;  
                }
            }
        } else {  删除值非null的元素,判断使用equals方法
            for (Node<E> x = first; x != null; x = x.next) {
                if (o.equals(x.item)) { 判断当前需要删除的数据和节点中的数据是否相等
                    unlink(x);  删除指定的Node节点,并且返回Node中存储的数据
                    return true;
                }
            }
        }
        return false;
    }

   删除指定的Node节点,并且返回Node中存储的数据
   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) { 如果当前节点的前一个节点为null,则表示当前节点为头节点
            first = next;  使头指针指向当前节点的下一个节点
        } else { 如果不是头节点
            prev.next = next;   上一个节点的下一个节点为当前节点的下一个节点,将当前节点从链表中剔除出来
            x.prev = null;  当前节点的上一个节点赋null值
        }
        if (next == null) {如果当前节点的下一个节点为null,则表示当前节点为尾节点
            last = prev; 使尾指针指向当前节点的上一个节点
        } else {  如果不是尾节点
            next.prev = prev; 下一个节点的上一个节点引用值为当前节点的上一个节点,将当前节点从链表中剔除出来
            x.next = null; 当前节点的下一个节点赋null值
        }
        x.item = null; 将当前节点的数据赋null值
        size--; 链表中的元素个数-1
        modCount++; 修改次数+1
        return element; 返回当前节点原来的数据
    }
    
    --------------------------------------------------------------------------------

按照指定的索引序号删除对应的元素
同时返回删除元素的具体数据值
    public E remove(int index) {
        checkElementIndex(index);  检查序号值是否合法,不合法抛出异常IndexOutOfBoundsException  index >= 0 && index < size
        return unlink(node(index));  首先查找指定索引序号对应的节点对象,然后删除对应的节点,返回原来节点上存储的具体数据
    }

修改操作
 public E set(int index, E element) {
        checkElementIndex(index);
        Node<E> x = node(index);
        E oldVal = x.item;  //获取原始节点存储的数据
        x.item = element;  //修改节点上的数据为新值
        return oldVal;  //返回原始存储的数据
    }

查找操作
如果找到则返回索引序号,如果没有找到则返回-1
    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;
    }
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值