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

原理:
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!

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

@Override
public 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,然后增加元素数量,计数器数量,完成整个添加操作

  • 增加(指定位置)
@Override
public 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 这里逻辑应该都不陌生了。接下来贴出删除等操作,大家掌握的思想,看起来就容易多了

  • 删除
@Override
public 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();
}
  • 修改
@Override
public 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();
}
  • 查找
@Override
public 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();
}

猜你喜欢

转载自blog.csdn.net/omyrobin/article/details/78602043
今日推荐