Java8 LinkedList的底层实现

来源:互联网 发布:ssH访问境外服务器端口 编辑:程序博客网 时间:2024/05/23 01:57

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类中所有的操作分步抽取出来,将每一步形成一个个独立的接口,这点在于重复的操作调用上提供了方便,也减少了代码量,是一种可以借鉴的代码习惯