基本介绍
LinkedList
底层实现了双向链表
和双端队列
特点- 可以添加任意元素(元素可以重复),包括
null
- 线程不安全,没有实现同步
底层操作机制
-
LinkedList
底层维护了一个双向链表. -
LinkedList
中维护了两个属性first
和last
分别指向首节点和尾节点
-
每个节点(Node对象),里面又维护了
prev、next、item
三个属性,其中通过prev指向前一个
,通过next指向后一个节点
。最终实现双向链表 -
LinkedList
的元素的添加和删除,不是通过数组完成的,相对来说效率较高。
-
模拟一个简单的双向链表
package collection_;
/**
* @Author: Gin
* @Description: 模拟一个简单的双向链表
* @Modified By: Gin
* @Date: Created in 17:18 2021/9/16
*/
public class List {
public static void main(String[] args) {
Node gin = new Node("Gin");
Node sherry = new Node("Sherry");
Node vermouth = new Node("Vermouth");
// 连接三个结点,形成双向链表
gin.next = sherry;
sherry.next = vermouth;
vermouth.pre = sherry;
sherry.pre = gin;
// 让 first 结点指向 Gin
// 让 last 结点指向 Vermouth
Node first = gin;
Node last = vermouth;
// 演示:从头到尾遍历
System.out.println("==从头到尾遍历==");
while(true){
if(first == null){
break;
}
System.out.println(first);
first = first.next;
}
// 演示:从尾到头遍历
System.out.println("==从尾到头遍历==");
while(true){
if(last == null){
break;
}
System.out.println(last);
last = last.pre;
}
// 再 Sherry 和 Vermouth 之间插入 Conan
Node conan = new Node("Conan");
sherry.next = conan;
conan.next = vermouth;
conan.pre = sherry;
vermouth.pre = conan;
// 遍历
System.out.println("==插入新数据后==");
first = gin;
while(true){
if(first == null){
break;
}
System.out.println(first);
first = first.next;
}
}
}
// 定义一个 Node 类,表示双向链表的一个结点
class Node{
public Object item; // 真正存放数据
public Node next; // 指向下一个结点
public Node pre; // 指向上一个结点
public Node(Object name) {
this.item = name;
}
public String toString(){
return "Node name = " + item;
}
}
LinkedList 底层代码
package collection_;
import java.util.Iterator;
import java.util.LinkedList;
/**
* @Author: Gin
* @Description: 演示:LinkedList
* @Modified By: Gin
* @Date: Created in 20:51 2021/9/16
*/
public class LinkedListDetails {
public static void main(String[] args) {
LinkedList linkedList = new LinkedList();
// new LinkedList() 方法底层:就是创建一个空的列表,且 first、last 都为 null
/*
public LinkedList() {
}
*/
linkedList.add(1);
/*
// add() 方法:
public boolean add(E e) {
linkLast(e);
return true;
}
// linkLast() 方法:
void linkLast(E e) {
final Node<E> l = last; // last 的指向赋给 l.【原链表如果没有数据,则 l 指向为 null,如果有数据,则 l 指向为最后一个元素】
final Node<E> newNode = new Node<>(l, e, null); // 创建新结点 newNode 内容为 e,将 l 的指向赋给 e 的 prev
last = newNode; // 将新结点 newNode 赋给 last 的指向,此时新结点 newNode 为双向链表的最后一个元素
if (l == null) // 判断 l 的指向是否为 null,
first = newNode; // l 的指向为 null 则将新结点 newNode 赋给 first 的指向
else
l.next = newNode; // l 的指向不为 null 则将 l.next 指向赋给新结点 newNode
size++; // 链表大小 + 1
modCount++; // 对链表的操作次数 + 1
}
// linkLast() 方法中的 final Node<E> newNode = new Node<>(l, e, null) 底层:
private static class Node<E> {
E item;
Node<E> next;
Node<E> prev;
Node(Node<E> prev, E element, Node<E> next) { // 三个参数分别为 prev、element、next
this.item = element;
this.next = next;
this.prev = prev;
}
}
*/
linkedList.add(2);
linkedList.add(3);
System.out.println(linkedList);
// 删除方法
linkedList.remove(); // 默认删除第一个元素
/*
// .remove() 方法的底层:
public E remove() {
return removeFirst();
}
// removeFirst() 方法:
public E removeFirst() {
final Node<E> f = first; // 判断链表是否为空,为空则抛异常
if (f == null)
throw new NoSuchElementException();
return unlinkFirst(f); // 执行删除方法
}
// unlinkFirst() 方法:
private E unlinkFirst(Node<E> f) { // f 为第一个结点
// assert f == first && f != null;
final E element = f.item; // 将 f 结点的内容赋给 element 用于返回
final Node<E> next = f.next; // 将 f.next 的指向赋给 next 结点
f.item = null; // 将 f 结点的内容设置为 null
f.next = null; // help GC // 将 f.next 的指向设置为 null,并请求 GC 回收
first = next; // 将 first 指向 next 结点
if (next == null) // 如果 next 结点为空,则表示链表只有一个结点,且已经被删除,此时链表为 null
last = null; // 将 last 指向 null
else // 如果 next 结点不为 null:
next.prev = null; // 则将 next 结点的 prev 设置为 null,即 next 结点为第一个结点
size--; // 链表的大小 - 1
modCount++; // 对链表的修改次数 + 1
return element; // 返回删除的元素
}
*/
System.out.println(linkedList);
// 修改
linkedList.set(1, 356);
System.out.println(linkedList);
// 迭代器遍历
System.out.println("迭代器遍历==========");
Iterator iterator = linkedList.iterator();
while (iterator.hasNext()) {
Object next = iterator.next();
System.out.println(next);
}
// 增强for
System.out.println("增强 for ===========");
for (Object o : linkedList) {
System.out.println(o);
}
// 普通 for
System.out.println("普通 for ============");
for (int i = 0; i < linkedList.size(); i++) {
System.out.println(linkedList.get(i));
}
}
}