LinkedList源代码阅读

LinkedList是一个基于双向链表实现的列表,不同于ArrayList的动态数组。它在添加或删除元素时无需移动元素,具有高效插入和删除性能。LinkedList没有扩容概念,每次添加元素会创建新节点。常用方法包括add(Ee)、addFirst(Ee)、addLast(Ee)、get(intindex)、indexOf(Objecto)、remove()等。删除元素通过unlink方法实现,支持按元素和下标删除。
摘要由CSDN通过智能技术生成

1.1  LinkedList的数据结构

LinkedList与ArrayList类都实了List接口,但LinkedList与ArrayList不同的是,它是基于双向链表实现数据的存储,链表是由若干个Node对象组成。添加或删除元素时不需要移动其他元素。

1.2  扩容方式  

由于它采用的使链表结构,所以它并不存在所谓的扩容方式,每次添加元素都会创建新的Node节点并分配空间,在内存中分配的空间并不连续。

2.  常用方法

2.1  添加元素

2.1.1  boolean add(E e):默认将元素添加到链表尾部,若添加成功返回true。

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);
        last = newNode;
        if (l == null)
            first = newNode;
        else
            l.next = newNode;
        size++;
        modCount++;
    }

添加元素底层源码(linkLast方法):将链表尾结点指向结点l,同时创建新结点并将新添加元素放入新结点。再将新结点指向尾结点。接下来判断结点l是否为空,若是,则新结点既是头结点也是尾结点;否则将新结点指向l结点的下一个结点。最后链表长度加一。

2.1.2  void  addFirst(E e):将元素添加到集合头部。

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


 private void linkFirst(E e) {
        final Node<E> f = first;
        final Node<E> newNode = new Node<>(null, e, f);
        first = newNode;
        if (f == null)
            last = newNode;
        else
            f.prev = newNode;
        size++;
        modCount++;
    }

2.1.3  void  addLast(E e):将元素添加到集合头部。

  public void addLast(E e) {
        linkLast(e);
    }

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

2.2 获取元素

2.2.1  E get(int index):get方法是通过遍历链表,查找指定下标出的元素,并且返回该元素。

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

2.2.2  E  getFirst():获取链表中头元素。

 public E getFirst() {
        final Node<E> f = first;
        if (f == null)
            throw new NoSuchElementException();
        return f.item;
    }

2.2.3  E  getLast():获取链表中尾元素。

public E getLast() {
        final Node<E> l = last;
        if (l == null)
            throw new NoSuchElementException();
        return l.item;
    }

2.3  查找元素

2.3.1  int indexOf(Object o):indexOf方法查找指定元素的下标位置,若存在返回下标值,否则返回-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;
    }

indexOf方法底层源码实现:先定义一个计数器index,接着判断传入元素是否为空,若是,则遍历链表并判断元素是否为空,若是空就返回index(下标);若传入元素不为空,则判断链表元素是否等于传入元素,若等于则返回index(下标)。若没有则返回-1。

2.3删除元素

2.3.1  E remove():删除链表头元素,返回删除元素。

boolean remove(Object o):删除链表中指定元素。若删除成功,返回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;
    }



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;

        if (prev == null) {
            first = next;
        } else {
            prev.next = next;
            x.prev = null;
        }

        if (next == null) {
            last = prev;
        } else {
            next.prev = prev;
            x.next = null;
        }

        x.item = null;
        size--;
        modCount++;
        return element;
    }

底层源码:删除元素x,next为x下一个节点,prev为x的前一个节点,若prev为空,说明x为头结点,删除后next为头结点;next指向prev的下一个结点且x的前一个节点置空。next结点同理;最后链表长度减一。

2.3.2  E remove (int index):删除指定下标元素,返回删除元素。

public E remove(int index) {
        checkElementIndex(index);
        return unlink(node(index));
   }

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

 private boolean isElementIndex(int index) {
        return index >= 0 && index < size;
    }

2.3.3  E removeFirst():删除链表头元素,返回删除元素。

 public E removeFirst() {
        final Node<E> f = first;
        if (f == null)
            throw new NoSuchElementException();
        return unlinkFirst(f);
    }

2.3.4   E removeLast(): 删除链表尾元素,返回删除元素。

  public E removeLast() {
        final Node<E> l = last;
        if (l == null)
            throw new NoSuchElementException();
        return unlinkLast(l);
    }

2.4  将链表转为数组

2.4.1  T[ ]  toArray(T[ ] a):将链表转为数组,返回数组

 public Object[] toArray() {
        Object[] result = new Object[size];
        int i = 0;
        for (Node<E> x = first; x != null; x = x.next)
            result[i++] = x.item;
        return result;
    }

底层源码:创建一个数组result,遍历链表并将每个元素存入数组,最后返回数组。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值