Arraylist 的源码解析,请参考 ArrayList 源码解析,看完就明白系列<一>ArrayList 源码解析,看完就明白系列<二>
平常我们使用LinkedList,很简单,我们根据源码逐一分析下
LinkedList linkedList = new LinkedList();
linkedList.add("1");
linkedList.add("2");
linkedList.get(2);
linkedList.getFirst();
- 首先 new LinkedList(),查看源码可知 就是创建了一个空的LinkedList,还有一个是初始化一个有值的LinkedList
public class LinkedList<E>
extends AbstractSequentialList<E>
implements List<E>, Deque<E>, Cloneable, java.io.Serializable
{
transient int size = 0; //LinkedList 长度
/**
* 链表的头指针
* Invariant: (first == null && last == null) ||
* (first.prev == null && first.item != null)
*/
transient Node<E> first;
/**
* 链表的尾指针
* Invariant: (first == null && last == null) ||
* (last.next == null && last.item != null)
*/
transient Node<E> last;
/**
* 创建一个空的集合
*/
public LinkedList() {
}
/**
* 构造一个包含指定元素的列表
* 集合,按照集合返回的顺序
* 迭代器。
*
* @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);
}
}
2 添加元素 linkedList.add("1"); linkedList.add("2"); 就是对链接进行操作了
// linkedList.add();就是调用了 这个方法
public boolean add(E e) {
linkLast(e); //添加元素直接添加到链表尾部
return true; //true 添加成功
}
//插入到链表尾部
void linkLast(E e) {
final Node<E> l = last; //最后一个node 赋值给新建的节点 l
final Node<E> newNode = new Node<>(l, e, null); // newNode 则是 把新加的节点 //e的 prev 前节点指向 上一次的last节点
last = newNode; //整理完的newNode 设置成 尾部节点
if (l == null) // l == null 说明 当前集合没有值,直接把添加的元素 作为 链表头节点
first = newNode;
else //否则 链表有值,上一次的 尾节点的 next 指针 指向新添加的节点,由此 新添加节点的 //前指针 和 后指针 均以初始完成
l.next = newNode;
size++; //更新 集合长度
modCount++;//更新修改次数
}
//node 的结构
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;
}
}
3 查找 元素 linkedList.get(index); linkedList.getFirst();
//获取集合的第一个元素,
public E getFirst() {
final Node<E> f = first;
if (f == null)
throw new NoSuchElementException();
return f.item;
}
//获取集合的第二个元素
public E getLast() {
final Node<E> l = last;
if (l == null)
throw new NoSuchElementException();
return l.item;
}
//获取指定位置的元素
public E get(int index) {
checkElementIndex(index); //检查查找位置的合法性
return node(index).item;//返回查找的元素
}
//检查查找位置的合法性
private void checkElementIndex(int index) {
if (!isElementIndex(index))
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
//检查查找位置的合法性 是否大于0 并且小于集合的长度
private boolean isElementIndex(int index) {
return index >= 0 && index < size;
}
//查找元素
Node<E> node(int index) {
if (index < (size >> 1)) { // 判断查找的位置 是否 小于集合长度的一半,如果小于则 从头节点的next 指针 顺序找到指定位置 并返回结果
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;
}
}
简单总结下:
LinkedList 是双向链表,线程不安全,插入删除效率高
下节分析 源码
linkedList.set(index,""); linkedList.add(index,""); linkedList.remove(); linkedList.remove(index);