集合(二)LinkedList源码分析

集合(一)扒掉ArrayList的外衣

集合(二)LinkedList源码分析

集合(三)HashMap源码分析

LinkedList是什么?

* Doubly-linked list implementation of the {@code List} and {@code Deque}
* interfaces.  Implements all optional list operations, and permits all
* elements (including {@code null}).

 LinkedList是实现List和Deque的双向链表,可以作为队列或者双端队列,非线程安全。

/**
 * Constructs an empty list.
 */
public LinkedList() {
}

/**
 * Constructs a list containing the elements of the specified
 * collection, in the order they are returned by the collection's
 * iterator.
 *
 * @param  c the collection whose elements are to be placed into this list
 * @throws NullPointerException if the specified collection is null
 */
public LinkedList(Collection<? extends E> c) {
    this();
    addAll(c);
}

LinkedList可以直接将一个ArrayList添加到一个队列里面。

LinkedList的变量属性很简单size(集合长度)、first(头节点),last(尾节点)。其添加方法除了add()、addAll()还有addFirst(),addLast()。

我们重点看一下addAll的源码操作:

public boolean addAll(int index, Collection<? extends E> c) {
    //检查添加位置是否越界,只能在[0,size]区间添加
    checkPositionIndex(index);
    //添加的Collection转为数组
    Object[] a = c.toArray();
    int numNew = a.length;
    if (numNew == 0)
        return false;

    Node<E> pred, succ;
    if (index == size) {
        //从集合最后插入数据
        succ = null;
        pred = last;
    } else {
        //从集合中间插入数据  找到index位置的当前对象
        succ = node(index);
        pred = succ.prev;
    }
    //遍历数组按队列形式插入集合
    for (Object o : a) {
        @SuppressWarnings("unchecked") E e = (E) o;
        Node<E> newNode = new Node<>(pred, e, null);
        if (pred == null)
            first = newNode;
        else
            pred.next = newNode;
        pred = newNode;
    }

    if (succ == null) {
        last = pred;
    } else {
        pred.next = succ;
        succ.prev = pred;
    }
    //集合当前长度
    size += numNew;
    //操作次数+1
    modCount++;
    return true;
}

remove数据主要操作步骤查询到要删除的数据,将该数据的前一个对象和后一个对象绑在一起:

/**
 * Removes the element at the specified position in this list.  Shifts any
 * subsequent elements to the left (subtracts one from their indices).
 * Returns the element that was removed from the list.
 *
 * @param index the index of the element to be removed
 * @return the element previously at the specified position
 * @throws IndexOutOfBoundsException {@inheritDoc}
 */
public E remove(int index) {
    //检查移除数据的索引是否在[0,size)区间内
    checkElementIndex(index);
    //查找当前位置对象
    return unlink(node(index));
}
/**
 * Unlinks non-null node x.
 */
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;
}

LinkedList的插入删除操作大同小异:先找到、再关联前后对象。

在内存中,链表不是按顺序存放的,而是通过指针连在一起,为了访问某一元素,必须从链头开始顺着指针才能找到某一个元素。

与ArrayList比较:

  1. 数据结构不同,ArrayList是数组结构,LinkedList是链表结构;
  2. ArrayList查询数据比LinkedList快,在内存中数组为连续的内存块,而链表是靠指针连接的,后者在查询时需要移动指针从一端到另一端[0,size>>1)或者[size>>1,size)去查询;
  3. 添加和删除数据时,ArrayList需要移动数据,LinkedList效率高
  4. 两者都是非线程安全的,Vector是线程安全的
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值