LinkList分析

来源:互联网 发布:乐乎pt ipv4 编辑:程序博客网 时间:2024/06/05 17:08

linkedlist是基于链表的

transient int size = 0;//大小
transient Node<E> first;  //链表的头结点
transient Node<E> last; //链表的尾节点

节点类

private static class Node<E> {        E item;     //元素值        Node<E> next;   //链表的后一个节点        Node<E> prev;   //链表的前一个节点        Node(Node<E> prev, E element, Node<E> next) {            this.item = element;            this.next = next;            this.prev = prev;        }    }

add()方法

public boolean add(E e) {        linkLast(e);//在最后插入新节点        return true;    }public void add(int index, E element) {        checkPositionIndex(index);        if (index == size)            linkLast(element);        else            linkBefore(element, node(index));    }

插入尾节点

public void addLast(E e) {        linkLast(e);    }
void linkLast(E e) {        final Node<E> l = last;             //新建节点l        final Node<E> newNode = new Node<>(l, e, null);    //新建newNode节点,元素是e,前一个节点是l        last = newNode;//linkLast方法新建节点顺序往后加,所以newNode作为尾节点        if (l == null)            first = newNode;   //如果尾节点l是null        else            l.next = newNode; //否则,newNode作为l的下一个节点        size++;  //size+1        modCount++;//修改计数器+1    }

linkFirst()插入一个头结点

public void addFirst(E e) {        linkFirst(e);    }
private void linkFirst(E e) {        final Node<E> f = first;//f赋值之前的头结点        final Node<E> newNode = new Node<>(null, e, f);   //新建节点把之前的头结点作为新建节点的后一个节点        first = newNode;//对头结点赋值newNode        if (f == null)            last = newNode;        else            f.prev = newNode;//之前头结点的前一个节点赋值为newNode        size++;        modCount++;    }

在某个节点前插入

 void linkBefore(E e, Node<E> succ) {        // assert succ != null;        final Node<E> pred = succ.prev;//succ节点的前一个节点赋值给新建节点pred         final Node<E> newNode = new Node<>(pred, e, succ);  新建newNode 节点,newNode 的后一个节点是succ,前一个节点是pred,元素是e,就是e节点        succ.prev = newNode;//succ的前一个节点是newNode        if (pred == null)            first = newNode;        else            pred.next = newNode;        size++;        modCount++;    }

删掉头结点

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; //获取f节点的元素        final Node<E> next = f.next; //获取f节点的后一个节点        f.item = null;   //f节点元素置空        f.next = null; // help GC         first = next;   //将f的后一个节点当做头结点        if (next == null)            last = null;        else            next.prev = null;        size--;        modCount++;        return element;    }

删掉尾节点差不多

删掉某一个节点

public E remove(int index) {        checkElementIndex(index);        return unlink(node(index));    }
public boolean remove(Object o) {        if (o == null) { //o可以为空,linkedList可以存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;    }
E unlink(Node<E> x) {        // assert x != null;        final E element = x.item;    //获取x的元素        final Node<E> next = x.next;  //获取x的后一个节点        final Node<E> prev = x.prev;  //获取x的前一个节点        if (prev == null) {//如果prev == null说明x是头结点,删掉X后,头节点变成next            first = next;        } else {            prev.next = next;//x的前一个节点的后一个节点给next,因为x要被x删掉了            x.prev = null;   //x的前一个节点的后一个节点本来是指向x的,x没了要置空,删掉对x的引用,要GC回收        }        if (next == null) {            last = prev;        } else {            next.prev = prev;            x.next = null;        }//以上是对X的前一个节点和后一个节点的处理(pred和next)        x.item = null; //对X的值置空,彻底将X置空和X的引用置空,等待GC        size--;        modCount++;        return element;    }

得到头结点或者尾节点的值

public E getFirst() {        final Node<E> f = first;        if (f == null)            throw new NoSuchElementException();        return f.item;    }public E getLast() {        final Node<E> l = last;        if (l == null)            throw new NoSuchElementException();        return l.item;    }

是否包含某个元素

public boolean contains(Object o) {        return indexOf(o) != -1;    }
public int indexOf(Object o) {        int index = 0;        if (o == null) {            for (Node<E> x = first; x != null; x = x.next) {                if (x.item == null)                    return index;                index++;            }        } else {            for (Node<E> x = first; x != null; x = x.next) {                if (o.equals(x.item))                    return index;                index++;            }        }        return -1;    }

指定位置插入集合元素

public boolean addAll(int index, Collection<? extends E> c) {        checkPositionIndex(index);//检查index是否超出范围        Object[] a = c.toArray();//把c转化成普通数组        int numNew = a.length;  //a的长度        if (numNew == 0) //numNew =0代表c是空没得插入            return false;        Node<E> pred, succ;        if (index == size) {//index == size代表正好在结尾插入            succ = null;            pred = last;//pred就是尾节点了        } else {            succ = node(index);//正好在succ前插入            pred = succ.prev;//pred就是succ的前一个节点        }        for (Object o : a) {//循环数组            @SuppressWarnings("unchecked") E e = (E) o;//对e赋值            Node<E> newNode = new Node<>(pred, e, null);//新建节点newNode            if (pred == null)//如果是头结点,newNode作为头结点,只有数组的第一个元素有可能走这一步                first = newNode;            else                pred.next = newNode;//因为是在succ后插入,pred是succ的前一个节点,所以pred.next是指向新节点的            pred = newNode;        }        if (succ == null) {            last = pred;        } else {            pred.next = succ;//新加入的元素的最后一个元素的后一个节点是next             succ.prev = pred;        }        size += numNew;        modCount++;        return true;    }
public Object[] toArray() {        Object[] result = new Object[size];//新建数组        int i = 0;        for (Node<E> x = first; x != null; x = x.next)//循环赋值            result[i++] = x.item;        return result;    }

返回指定位置的元素

Node<E> node(int index) {        // assert isElementIndex(index);        if (index < (size >> 1)) {    //index < size / 2            Node<E> x = first;            for (int i = 0; i < index; i++)//链表结构不能像数组一样用下标,只能一个一个顺序找,当index在前一半的时候正向查找                x = x.next;            return x;        } else {            Node<E> x = last;            for (int i = size - 1; i > index; i--)//当index在后一半的时候反向查找,从最后开始倒序查                x = x.prev;            return x;        }    }

清空

public void clear() {        // Clearing all of the links between nodes is "unnecessary", but:        // - helps a generational GC if the discarded nodes inhabit        //   more than one generation        // - is sure to free memory even if there is a reachable Iterator        for (Node<E> x = first; x != null; ) {            Node<E> next = x.next;//循环所有节点,将他们的引用指向和元素值都置空            x.item = null;            x.next = null;            x.prev = null;            x = next;        }        first = last = null;        size = 0;        modCount++;    }

获取某个元素的值

public E get(int index) {        checkElementIndex(index);        return node(index).item;    }

set

public E set(int index, E element) {        checkElementIndex(index);        Node<E> x = node(index);//先找到节点        E oldVal = x.item;        x.item = element;        return oldVal;    }

返回元素位置,可以看出元素可以为null

//从前查public int indexOf(Object o) {        int index = 0;        if (o == null) {            for (Node<E> x = first; x != null; x = x.next) {                if (x.item == null)                    return index;                index++;            }        } else {            for (Node<E> x = first; x != null; x = x.next) {                if (o.equals(x.item))                    return index;                index++;            }        }        return -1;    }    //从后查public int lastIndexOf(Object o) {        int index = size;        if (o == null) {            for (Node<E> x = last; x != null; x = x.prev) {                index--;                if (x.item == null)                    return index;            }        } else {            for (Node<E> x = last; x != null; x = x.prev) {                index--;                if (o.equals(x.item))                    return index;            }        }        return -1;    }

push

public void push(E e) {        addFirst(e);    }

pop

public E pop() {        return removeFirst();    }