数据结构Collection-----LinkedList源码解析

来源:互联网 发布:python编辑器推荐sum 编辑:程序博客网 时间:2024/06/02 04:11

原理:
LinkedList不同于ArrayList,是一种的是双向链表的数据结构

继承关系

这里写图片描述

LinkedList:重要的属性和构造方法

public class LinkedList<E> extends AbstractSequentialList<E> implements        List<E>, Deque<E>, Queue<E>, Cloneable, Serializable {    //集合元素数量    transient int size = 0;    //空节点,很多操作都离不开它,在无参构造中进行初始化    transient Link<E> voidLink;    //内部类包装了元素    private static final class Link<ET> {        ET data;        Link<ET> previous, next;        Link(ET o, Link<ET> p, Link<ET> n) {            data = o;            previous = p;            next = n;        }    //无参构造,初始化了voidLink变量,并将其previous、next进行赋值    public LinkedList() {        voidLink = new Link<E>(null, null, null);        voidLink.previous = voidLink;        voidLink.next = voidLink;    }}

无参构造创建了一个Link的对象voidLink!

这里写图片描述
- 增加(无需指定位置)

@Overridepublic boolean add(E object) {    //直接调用addLastImpl方法    return addLastImpl(object);}private boolean addLastImpl(E object) {    //1.第一次添加,从无参构造上,可以发现voidLink的previous、next都是voidLink本身。    //2.集合中不止volidLink一个节点,从刚才1的注释顺序来看,voidLink.previous是之前的newLink,也就是上次新添加到队尾的节点    Link<E> oldLast = voidLink.previous;    //1.从内部类的构造来看,newLink的previous指向了oldLast,而oldLast是voidLink.previous,voidLink.previous又是voidLink本身。newLink的next指向了voidLink。    //2..从内部类的构造来看,newLink的previous指向了oldLast,而oldLast是voidLink.previous,voidLink.previous是之前的newLink(这次叫oldLast )。newLink的next指向了voidLink。    Link<E> newLink = new Link<E>(object, oldLast, voidLink);    //将voidLink.previous赋值为newLink    voidLink.previous = newLink;     //1.上文说过了oldLast就是voidLink本身,将voidLink.next赋值为newLink;     //2.上文说过了oldLast就是上次新添加到队尾的节点,将oldLast.next赋值为newLink;    oldLast.next = newLink;    //元素数量+1    size++;    //计数器+1    modCount++;    return true;}

画图来说明一下这个添加过程吧!
这里写图片描述

接下来我们再一次执行添加元素,相信大家根据源码就可以明白下面图片的内容了
这里写图片描述

总结来说,不指定index的add,直接加入到链表的结尾,将newLink的previous指向链尾的oldLast,next指向voidLind,然后voidLink的previous指向newLink,链尾的oldLast的next指向newLink,然后增加元素数量,计数器数量,完成整个添加操作

  • 增加(指定位置)
@Overridepublic void add(int location, E object) {    if (location >= 0 && location <= size) {        //初始化link,赋值为voidLink(空节点很重要的变量,现在看出来了吧,很多操作都离不开它)        Link<E> link = voidLink;        //采用二分法,如果是location在前半段,就从voidLink一路next下去向后查找,如果是后半段就一路prevvious像前查找。        if (location < (size / 2)) {            for (int i = 0; i <= location; i++) {                link = link.next;            }        } else {            for (int i = size; i > location; i--) {                link = link.previous;            }        }        Link<E> previous = link.previous;        Link<E> newLink = new Link<E>(object, previous, link);        previous.next = newLink;        link.previous = newLink;        size++;        modCount++;    } else {        throw new IndexOutOfBoundsException();    }}

相信大家看过之前的add 这里逻辑应该都不陌生了。接下来贴出删除等操作,大家掌握的思想,看起来就容易多了

  • 删除
@Overridepublic E remove(int location) {    if (location >= 0 && location < size) {        Link<E> link = voidLink;        if (location < (size / 2)) {            for (int i = 0; i <= location; i++) {                link = link.next;            }        } else {            for (int i = size; i > location; i--) {                link = link.previous;            }        }        Link<E> previous = link.previous;        Link<E> next = link.next;        previous.next = next;        next.previous = previous;        size--;        modCount++;        return link.data;    }    throw new IndexOutOfBoundsException();}
  • 修改
@Overridepublic E set(int location, E object) {    if (location >= 0 && location < size) {        Link<E> link = voidLink;        if (location < (size / 2)) {            for (int i = 0; i <= location; i++) {                link = link.next;            }        } else {            for (int i = size; i > location; i--) {                link = link.previous;            }        }        E result = link.data;        link.data = object;        return result;    }    throw new IndexOutOfBoundsException();}
  • 查找
@Overridepublic E get(int location) {    if (location >= 0 && location < size) {        Link<E> link = voidLink;        if (location < (size / 2)) {            for (int i = 0; i <= location; i++) {                link = link.next;            }        } else {            for (int i = size; i > location; i--) {                link = link.previous;            }        }        return link.data;    }    throw new IndexOutOfBoundsException();}