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