您的位置:首页 > 编程语言 > Java开发

Java8 LinkedList的底层实现

2017-08-27 23:49 253 查看
LinkedList的底层是通过双链表实现的,在linkedList中定义了一个Entry的静态内部类,如下:

private static class Node<E> {
E item;
Node<E> next;
Node<E> prev;
//node的定义
Node(Node<E> prev, E element, Node<E> next) {
this.item = element;
this.next = next;
this.prev = prev;
}
}


链表的初始化

public class LinkedList<E> extends AbstractSequentialList<E>
implements List<E>, Deque<E>, Cloneable, java.io.Serializable
{
transient int size = 0;

//这里相较java6的不同在于采用了双指针

transient Node<E> first;
transient Node<E> last;

public LinkedList() {
}
}


添加节点

//默认的add方法是在list的末尾添加
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;
//修改first和last的指针指向
if (l == null)
first = newNode;
else
l.next = newNode;
size++;
//这里的modCount是计算链表操作次数的计数器
modCount++;
}


删除节点(通过节点位置来删除节点)

public E remove(int index) {
checkElementIndex(index);
return unlink(node(index));
}
//判断index位置是否存在节点
private void checkElementIndex(int index) {
if (!isElementIndex(index))
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
private boolean isElementIndex(int index) {
return index >= 0 && index < size;
}
//移除该节点
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--;
modCount++;
return element;
}


移除节点(通过节点内容来移除)

注意:linkedList和arrayList中允许节点内容为空和节点内容重复,因此如果输入节点内容为空,需要判断链表中是否有节点内容为空;而如果在链表中有节点内容重复,则删除第一个节点内容相符的节点

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;
}


设置节点内容

public E set(int index, E element) {
//这里同样先判断节点位置是否存在
checkElementIndex(index);
Node<E> x = node(index);
E oldVal = x.item;
x.item = element;
return oldVal;
}


获取节点内容

public E get(int index) {
checkElementIndex(index);
return node(index).item;
}
Node<E> node(int index) {
//这里是用了位运算来判断index是否大于size的一半,如果是的话,则使用尾指针,否则使用前指针
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;
}
}


获取链表的大小

public int size() {
return size;
}


相对于java6而言,java8类中所有的操作分步抽取出来,将每一步形成一个个独立的接口,这点在于重复的操作调用上提供了方便,也减少了代码量,是一种可以借鉴的代码习惯
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  linkedlist java