Linkedlist的源码分析
官方文档解释:
List和Deque接口的双向链表实现。 实现所有可选的列表操作,并允许所有元素(包括null )。
对于双向链表,所有操作都按预期执行。 索引到列表中的操作将从开始或结束遍历列表,以更接近指定索引的为准。
请注意,此实现不是同步的。 如果多个线程并发访问一个链表,并且至少有一个线程在结构上修改了链表,则必须进行外部同步。 (结构修改是添加或删除一个或多个元素的任何操作;仅设置元素的值不是结构修改。)这通常是通过同步一些自然封装列表的对象来完成的。 如果不存在此类对象,则应使用Collections.synchronizedList方法“包装”该列表。 这最好在创建时完成,以防止对列表的意外不同步访问:
List list = Collections.synchronizedList(new LinkedList(...));
此类的iterator和listIterator方法返回的iterator是快速失败的:如果在创建迭代器后的任何时间以任何方式修改列表结构,除了通过 Iterator 自己的remove或add方法,迭代器将抛出ConcurrentModificationException 。 因此,面对并发修改,迭代器快速而干净地失败,而不是在未来不确定的时间冒着任意、非确定性行为的风险。
请注意,无法保证迭代器的快速失败行为,因为一般而言,在存在非同步并发修改的情况下不可能做出任何硬保证。 快速失败的迭代器会尽最大努力抛出ConcurrentModificationException 。 因此,编写一个依赖此异常来确保其正确性的程序是错误的:迭代器的快速失败行为应该仅用于检测错误。
此类是Java Collections Framework的成员。
这个官方解释和ArrayList的有很多相似的地方,因此这两个List只是实现不一样,但是一些规定是基本上一样的
源码分析:
transient int size = 0; /** * Pointer to first node. * Invariant: (first == null && last == null) || * (first.prev == null && first.item != null) */ transient Node<E> first; //指向第一个节点的指针 /** * Pointer to last node. * Invariant: (first == null && last == null) || * (last.next == null && last.item != null) */ transient Node<E> last;//指向最后一个节点的指针
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; } }
节点的类型
public LinkedList() { }
构造一个空的列表
public LinkedList(Collection<? extends E> c) { this(); addAll(c); }
按照集合的迭代器返回的顺序构造一个包含指定集合元素的列表
public boolean addAll(Collection<? extends E> c) { return addAll(size, c); }
按照指定集合的迭代器返回的顺序,将指定集合中的所有元素追加到此列表的末尾。 如果在操作进行时修改了指定的集合,则此操作的行为未定义。 (请注意,如果指定的集合是这个列表,并且它是非空的,则会发生这种情况。)
public boolean addAll(int index, Collection<? extends E> c) { checkPositionIndex(index); Object[] a = c.toArray(); int numNew = a.length; if (numNew == 0) return false; Node<E> pred, succ; //succ指的是待添加节点 pred指的是待添加节点的前一个节点 if (index == size) { succ = null; pred = last; } else { 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; modCount++; return true; }
从指定位置开始,将指定集合中的所有元素插入此列表。 将当前在该位置的元素(如果有)和任何后续元素向右移动(增加它们的索引)。 新元素将按照指定集合的迭代器返回的顺序出现在列表中。
Node<E> node(int index) { // assert isElementIndex(index); if (index < (size >> 1)) { Node<E> x = first; for (int i = 0; i < index; i++) x = x.next; return x; } else { Node<E> x = last; for (int i = size - 1; i > index; i--) x = x.prev; return x; } }
返回指定元素索引处的(非空)节点,此处对遍历进行了一个优化,不是盲目地从链头遍历到链尾,而是先判断更靠近哪一边,然后再进行遍历。

浙公网安备 33010602011771号