日常开发中,保存一组数据使用的最多的就是 ArrayList, 其次就是 LinkedList 了。
我们知道 ArrayList 是以数组实现的,遍历时很快,但是插入、删除时都需要移动后面的元素,效率略差些。
LinkedList不是做指定位置插入的话,效率和ArrayList其实是差不多的,当做指定位置插入也就是往中间插入效率比ArrayList快不了多少;做删除也是这个原理,所以在开发中用到集合不怎么会去用到这个LinkedList的一个原因,而且LinkedList的使用场景非常的少。
当要遍历LinkedList里面的数据时,不能使用for(int i = 0;......)这种形式来拿数据,效率极差,LinkedList当中集成了一个迭代器去进行遍历,也可以用增强for(就是迭代器)去遍历,效率要块n多倍;
因为使用迭代器的话里面有个指针每次读完数据并且next()的时候指针会跟着移动每次,基于链表可以高效遍历拿值
使用for(int i = 0;......)的话用get(i)拿值,拿到第i个值就需要迭代i次时间复杂度是平方阶O(n²),及其耗时
LinkedList源码解析
public class LinkedList<E>
extends AbstractSequentialList<E>
implements List<E>, Deque<E>, Cloneable, java.io.Serializable
AbstractSequentialList 继承自 AbstractList是LinkedList的父类,是List接口的简化版实现。
AbstractSequentialList 只支持按次序访问,而不像AbstractList那样支持随机访问。
实现了Deque<E>,支持两端元素插入和移除的线性集合。
既具有队列FIFO(先进先出)特点又具有栈LIFO(后进先出)特点,既是队列又是栈。
所以LinkedList还可以当作栈来使用;
LinkedList每次添加 会在堆中随机创建一个Node 然后将一个一个Node串起来形成链表
//LinkedList中的三个属性
//集合里面的元素条数
transient int size = 0;
//从头开始
transient Node<E> first;
//从尾开始
transient Node<E> last;
LinkedList就是基于一个Node对象来讲一个一个的引用链接起来的操作
用first和last来控制LinkedList数据操作
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一层一层嵌套一层一层引用链接起来实现双端链表
当LinkedList插入4条数据时 里面Node<E> first;和Node<E> last;的运行结果