public LinkedList(Collection<? extends E> c) {
this();
addAll(c);
}
3、添加操作
(1)普通添加
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++; //集合长度 +1
modCount++; //集合操作指令数 +1
}
(2)特定位置添加:
public void add(int index, E element) {
checkPositionIndex(index); // 检查插入位置是否越界
if (index == size) //如果是往最后一个位置插,就是普通插入
linkLast(element);
else //往中间插入
linkBefore(element, node(index));
}
//把当前位置的数往后移,把要插入的数插入进去,(旧数的前一个节点变成了新数的前一个节点,新数的后一个节点就是旧数,旧数的前一个节点变成了新数)
void linkBefore(E e, Node<E> succ) { //e当前要插入的数据 succ是当前位置上的数
// assert succ != null;
final Node<E> pred = succ.prev; //当前旧数的前一个
final Node<E> newNode = new Node<>(pred, e, succ); //新的节点
succ.prev = newNode;
if (pred == null)
first = newNode;
else
pred.next = newNode;
size++; //长度 +1
modCount++; //操作指令数 +1
}
(3)插入头位置:
private void linkFirst(E e) {
final Node<E> f = first;
final Node<E> newNode = new Node<>(null, e, f);
first = newNode;
if (f == null)
last = newNode;
else
f.prev = newNode;
size++;
modCount++;
}
(4)插入尾位置:
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++;
}
4、删除操作
(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; //就把当前位置的前一个节点的下一个节点变成当前位置的下一个节点
x.prev = null; //当前位置的前一个节点设置为空,也就是说当前位置没有前节点了
}
if (next == null) { //如果后节点没有数据,说明删的是尾节点
last = prev; //把当前位置的前节点变成尾节点
} else {
next.prev = prev; //当前位置后节点的前节点变成当前位置的前节点
x.next = null;//把当前位置的后节点设置为空
}
x.item = null; //把当前位置的值设置为空
size--; //长度 -1
modCount++; //操作指令数 +1
return element; //返回你已经删除的节点数据
}
(2)删除当前值:
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;
}
(3)删除头:
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;
}
(4)删除尾:
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;
l.item = null;
l.prev = null; // help GC
last = prev;
if (prev == null) //如果他没有前节点说明当前节点即是头又是尾
first = null; //把头设置为空
else
prev.next = null;
size--;
modCount++;
return element;
}
5、查找当前值
Node<E> node(int index) {
// assert isElementIndex(index);
//用当前位置与集合的长度/2进行比较
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;
}
}
LinkedList1、特点底层是一个链式结构的集合是双向链表,当前节点都会保存前一个节点的引用和后一个节点的引用在内存空间中存储不是连续的,并且也不是循序的允许空值存在2、 构造方法(1)无参: public LinkedList() { }(2)包含另一个集合: public LinkedList(Collection<? extends ...