LinkedList
LinkedList的定义:
public class LinkedList<E>
extends AbstractSequentialList<E>
implements List<E>, Deque<E>, Cloneable, java.io.Serializable
{...}复制代码
- LinkedList<E>:说明它支持泛型
- extends AbstractSequentialList<E>:说明LinkedList不支持随机访问,只支持按次序访问
- 实现了List<E>接口:说明它支持集合的一般操作
- 实现了Deque<E>接口:说明它可用作队列和双向队列
- 实现了Cloneable、Serializable:可调用clone()方法和可序列化。
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;
}
}
复制代码
Node是双向链表节点所对应的数据结构,包括的属性是:当前节点的值,上一个节点,下一个节点。
构造方法
public LinkedList() {
}
//接收一个Collection参数c,调用第一个构造方法,并把c中所有元素添加到链表中
public LinkedList(Collection<? extends E> c) {
this();
addAll(c);
}复制代码
常用方法
- removeFirst():删除表头元素
- removeLast():删除表尾元素
- addFirst(E e):在表头插入指定元素
- addLast(E e):在表尾插入指定元素
- contains(Object o):判断链表是否包含指定对象
- add(E e):在表尾插入指定元素
- remove(Object o):正向遍历链表,删除第一个值为指定对象的节点
- addAll(Collection<? extends E> c):在表尾插入指定集合
- clear():清除链表中的所有元素
LinkedList的遍历方式
LinkList遍历不用for循环,因为用迭代器iterator遍历比for快。
for循环遍历:
for(int i=0; i<list.size(); i++) {
list.get(i);
}复制代码
//LinkedList的get方法源码
public E get(int index) {
checkElementIndex(index);
return node(index).item;
}
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;
}
}复制代码
迭代器遍历:
List<Integer> list = new LinkedList<>();
Iterator<Integer> iterator = list.listIterator();
while (iterator.hasNext()) {
Integer i = iterator.next();
}复制代码
//next方法
public E next() {
checkForComodification();
if (!hasNext())
throw new NoSuchElementException();
lastReturned = next;
next = next.next;
nextIndex++;
return lastReturned.item;
}复制代码
从源码可以看出,LinkedList如果用for循环遍历,get方法里面会再次使用循环遍历链表,时间复杂度是O(n²);如果有迭代器遍历,因为next的存在,得到当前项不需要时间,所以只需要使用一次循环,时间复杂度是O(n)。
ArrayList和LinkedList的区别
- ArrayList是基于动态数组的数据结构,LinkedList是基于链表(双向链表)的数据结构
- 对于随机访问,ArrayList要比LinkedList方便,因为LinkedList是移动指针
- 关于增加和删除操作,LinkedList比较方便,ArrayList要慢慢移动元素位置(索引)
参考资料:
为什么使用迭代器iterator遍历Linkedlist要比普通for快