首先和数组一样,LinkedList也是一种线性数据结构,用链表实现的集合,元素有序且可以重复可以为null
由于其允许内存进行动态分配,意味着内存分配是由编译器在运行时完成的,我们无需在LinkedList声明的时候指定大小
其也不需要在连续的位置上存储元素,因为节点可以通过引用指定下一个节点或者前一个节点,导致插入和删除的成本很低。
LinkedList的实现是基于双向链表的,且头结点中不存放数据
和 ArrayList 一样,不是同步容器
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SAFdrM8w-1597210837179)(https://raw.githubusercontent.com/iszhonghu/Picture-bed/master/img/20200811170511.png)]
也实现了Cloneable接口和Serializable接口,分别用来支持克隆以及序列化。
其是一个继承自AbstractSequentiaList的双向链表,因此它也可以被当做堆栈、队列或双堆队列进行操作
由于其实现了List接口,所以能对它进行队列操作
由于实现了Deque接口,所以能将LinkedList当做双端队列使用
LinkedList中的每一个元素都可以称之为节点,每一个节点都包含三个项目,其一就是元素本身,其二是执行像一个元素的引用地址,其三是指向上一个元素的引用地址
Node是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;
}
}
LinkedList有两个构造函数,一个是默认的空的构造函数,一个是将已有元素的集合Collection的实例添加到LinkedList中,调用的是addAll方法。
LinkedList有很多add方法,但是每次添加元素只是改变对应节点的上下指针引用,而且没有扩容,所以效率还是很不错的
将指定元素添加到链表头
public void addFirst(E e) {
linkFirst(e);
}
private void linkFirst(E e) {
final Node<E> f = first;// 将头节点赋值给f
final Node<E> newNode = new Node<>(null, e, f);//将指定元素构造成一个新节点,此节点的指向下一个节点的引用为头节点
first = newNode;
if (f == null)
last = newNode;
else
f.prev = newNode;
size++;
modCount++;
}
和插入头节点差不多,逻辑层面基本一样
void linkLast(E e) {
final Node<E> l = last;
final Node<E> newNode = new Node<>(l, e, null);
last = newNode;
if (l == null)
first = newNode;
else
l.next = newNode;
size++;
modCount++;
}
将指定的元素插入此列表中的指定位置
按照指定集合的迭代器返回的顺序,将指定集合中的所有元素追加到此列表的末尾
删除元素和添加元素基本一致,就是改变对应元素指向上一节点和下一节点的引用即可。
从列表中移除第一个元素并返回该元素
从列表中删除最后一个元素并返回该元素
删除此列表中指定位置的元素
如果存在,则从该列表中删除指定元素的第一次出现
用指定的元素替换此列表中指定位置的元素,主要是通过node(index)方法获取指定索引位置的几点,然后修改此节点位置的元素
返回此列表中第一个元素
返回此列表中的最后一个元素
返回指定索引处的元素
返回此列表中指定元素第一次出现的索引,如果此列表中不包含元素,则返回-1
需要注意的是,modCount 字段,前面我们在增加和删除元素的时候,都会进行自增操作 modCount,这是因为如果想一边迭代,一边用集合自带的方法进行删除或者新增操作,都会抛出异常。(使用迭代器的增删方法不会抛异常)
主要利用get(int index)方法
Iterator<String> listIt = linkedList.listIterator();
9 while(listIt.hasNext()){
10 System.out.print(listIt.next()+" ");
11 }
12
13 //通过适配器模式实现的接口,作用是倒叙打印链表
14 Iterator<String> it = linkedList.descendingIterator();
15 while(it.hasNext()){
16 System.out.print(it.next()+" ");
17 }
在其集合中也有一个内部类Listltr,
其底层使用的也是迭代器本质一样
迭代器和for循环效率差异
普通for循环:每遍历一个索引的元素之前,都要访问之前的所有索引
16 System.out.print(it.next()+" ");
17 }
在其集合中也有一个内部类Listltr,
##### foreach循环
其底层使用的也是迭代器本质一样
> 迭代器和for循环效率差异
>
> 普通for循环:每遍历一个索引的元素之前,都要访问之前的所有索引
>
> 迭代器:每次访问一个元素以后,都会用游标记录当前访问元素的位置,遍历一个元素,记录一个元素