LinkedList,链表,一个节点挂着另外一个节点
优点在哪儿?往这个里面中间插入一些元素,或者不停的往list里插入元素,都没关系,因为人家是链表,中间插入元素,不需要跟ArrayList数组那样子,挪动大量的元素的,不需要,人家直接在链表里加一个节点就可以了
如果你不断的往LinkedList中插入一些元素,大量的插入,就不需要像ArrayList数组那样还要去扩容啊什么的,人家是一个链表,就是不断的把新的节点挂到链表上就可以了
LinkedList的优点,就是非常适合各种元素频繁的插入里面去
LinkedList的缺点,不太适合在随机的位置,获取某个随机的位置的元素,比如LinkedList.get(10),这种操作,性能就很低,因为他需要遍历这个链表,从头开始遍历这个链表,直到找到index = 10的这个元素为止
ArrayList.get(10),不需要遍历,直接根据内存的地址,根据你指定的index,直接定位到那个元素,不需要遍历数组什么的
ArrayList和LinkedList区别,数组和链表的区别,优缺点主要就是这样子
LinkedList:适合,频繁的在list中插入和删除某个元素,然后尤其是LinkedList他其实是可以当做队列来用的,先进先出,在list尾部怼进去一个元素,从头部拿出来一个元素。如果要在内存里实现一个基本的队列的话,可以用LinkedList
public boolean add(E e) {
//核心添加逻辑
linkLast(e);
//固定返回
return true;
}
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++;
}
public void add(int index, E element) {
//索引边界检查
checkPositionIndex(index);
//选择插入策略
if (index == size)
linkLast(element);//情况1,尾部插入
else
//情况2,在指定节点插入
//根据给定的 `index` 找到双向链表中的对应节点
linkBefore(element, node(index));
}
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;//向后移动index次
return x;//返回目标节点
} else {
//从后往前遍历
//从尾节点开始
Node<E> x = last;
//向前移动(size-1-index)
for (int i = size - 1; i > index; i--)
x = x.prev;
//返回目标节点
return x;
}
}
public void addFirst(E e) {
linkFirst(e);
}
private void linkFirst(E e) {
final Node<E> f = first;//暂存原头节点
final Node<E> newNode = new Node<>(null, e, f);//创建新节点(prev=null, next指向原头节点)
first = newNode;//更新头指针指向新节点
//处理链表状态
if (f == null)
last = newNode;//原链表为空-->新节点也是尾节点
else
f.prev = newNode;//原链表非空-->原头节点的prev指向新节点
size++;//元素数量+1
modCount++;//结构性修改计数+1(支持迭代器快速失败)
}
LinkedList可以作为一个队列来使用
offer() == add(),就是在队列尾部入队,将一个元素插入队列尾部,
offerFirst()头部插入元素,offerLast()尾部插入元素
poll(),从队列头部出队
peek(),获取队列头部的元素,但是头部的元素不出队
public boolean offer(E e) {
return add(e);
}
public boolean offerFirst(E e) {
addFirst(e);
return true;
}
public boolean offerLast(E e) {
addLast(e);
return true;
}
public E poll() {
//获取链表头节点
final Node<E> f = first;
//若头节点为空,则返回空。否则调用unlinkFirst(f)移除头节点
return (f == null) ? null : unlinkFirst(f);
}
private E unlinkFirst(Node<E> f) {
//断言 f必须是头节点且非null
// assert f == first && f != null;
//获取头节点存储的元素值
final E element = f.item;
//获取头节点的后继节点(可能为null)
final Node<E> next = f.next;
//清空节点引用(帮助GC回收)
f.item = null;
f.next = null; // help GC 断开头节点与链表连接
//更新头节点指向后继节点
first = next;
//处理链表状态
if (next == null)
//情况A 无后续节点
last = null;
else
//情况B 后继节点成为新头节点,需清空前驱指针
next.prev = null;
//更新元数据
size--;//元素计数减1
modCount++;//结构性修改计数+1
return element;
}
public E peek() {
final Node<E> f = first;
return (f == null) ? null : f.item;
}
public E get(int index) {
checkElementIndex(index);//索引合法性校验
return node(index).item;
}
public E getLast() {
final Node<E> l = last;
if (l == null)
throw new NoSuchElementException();
return l.item;
}
public E getFirst() {
final Node<E> f = first;
if (f == null)
throw new NoSuchElementException();
return f.item;
}
list.remove();
public E remove() {
return removeFirst();
}
public E removeFirst() {
final Node<E> f = first;
if (f == null)
throw new NoSuchElementException();
return unlinkFirst(f);
}
private E unlinkFirst(Node<E> f) {
// assert f == first && f != null;
final E element = f.item;//保存被删节点的数据,用于返回
final Node<E> next = f.next;//保存后继节点(新头节点候选)
f.item = null; //清空旧头节点引用(GC优化)
f.next = null; // help GC,显式断开引用,加速垃圾回收
first = next; //头节点指向后继节点(新头节点)
if (next == null) //链表仅有一个节点
last = null; //清空尾指针(链表变空)
else
next.prev = null; //新头节点前驱置空(断开与旧节点的联系)
size--; //元素数量减1
modCount++;//结构性修改计数+1(触发迭代器快速失败)
return element;
}
list.remove("test");
public boolean remove(Object o) {
if (o == null) {
for (Node<E> x = first; x != null; x = x.next) {
if (x.item == null) {
unlink(x);
return true;
}
}
} else {
for (Node<E> x = first; x != null; x = x.next) {
if (o.equals(x.item)) {
unlink(x);
return true;
}
}
}
return false;
}
list.remove(1);
public E remove(int index) {
checkElementIndex(index);
return unlink(node(index));
}
E unlink(Node<E> x) {
// assert x != null;
//保存被删节点的数据
final E element = x.item;
//保存后继节点
final Node<E> next = x.next;
//保存前驱节点
final Node<E> prev = x.prev;
//目标节点是头节点
if (prev == null) {
first = next;//更新头指针指向后继节点
} else {//目标节点非头节点
//前驱节点直接链接到后继节点
prev.next = next;
//断开目标节点对前驱的引用(加速GC)
x.prev = null;
}
//目标节点是尾节点
if (next == null) {
//更新尾指针指向前驱节点
last = prev;
} else {//目标节点非尾节点
//后继节点直接链接到前驱节点
next.prev = prev;
//断开目标节点对后继的引用
x.next = null;
}
//清空数据引用
x.item = null;
//元素数量减1
size--;
//结构性修改计数+1(触发迭代器快速失败)
modCount++;
//返回被删除的数据
return element;
}
list.removeFirst();
public E removeFirst() {
final Node<E> f = first;
if (f == null)
throw new NoSuchElementException();
return unlinkFirst(f);
}
private E unlinkFirst(Node<E> f) {
// assert f == first && f != null;
final E element = f.item;
final Node<E> next = f.next;
f.item = null;
f.next = null; // help GC
first = next;
if (next == null)
last = null;
else
next.prev = null;
size--;
modCount++;
return element;
}
list.removeLast();
public E removeLast() {
final Node<E> l = last;
if (l == null)
throw new NoSuchElementException();
return unlinkLast(l);
}
private E unlinkLast(Node<E> l) {
// assert l == last && l != null;
//保存尾节点的数据(用于返回)
final E element = l.item;
//保存尾节点的前驱节点
final Node<E> prev = l.prev;
//清空旧尾节点引用(GC优化)
l.item = null;
l.prev = null; // help GC.显示断开引用,加速垃圾回收
//尾指针指向前驱节点(新尾节点)
last = prev;
//链表只有一个节点
if (prev == null)
//清空头指针(链表变空)
first = null;
else
//新尾节点的next置空-尾部无后继
prev.next = null;
size--; //元素数量减1
modCount++;
return element;
}