Java数据结构-LinkedList(四)

本文深入剖析双向链表的概念及其实现原理,并详细解读Java中LinkedList类的源码,探讨其作为队列、堆栈及双端队列的特性与应用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

参考博客:http://www.cnblogs.com/skywang12345/p/3561803.html,表示感谢!

LinkedList 是List接口的一个基于双向链表的实现类,继承了AbstractSequentialList类,实现了List接口,Queue接口(队列),Deque(双端队列),Cloneable接口,Serializable接口。因此LinkedList具有队列的特点,可以作为堆栈,队列,双端队列使用。

和ArrayList一样,LinkedList也是非同步的,如果不需要使用队列的特性的话,一般使用ArrayList。

遍历LinkedList时,使用removeFist()或removeLast()效率最高。但用它们遍历时,

会删除原始数据;若单纯只读取,而不删除,应该使用增强for循环或者iterator的方式,

千万不要使用角标访问的形式来遍历。

LinkedList与Collection关系如下图:



LinkedList的本质是一个双向链表,那么什么是双向链表呢?

双向链表(双链表)是链表的一种。双链表由一个个节点组成,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。一般我们都构造双向循环链表。

双链表的示意图如下:

表头为空,表头的后继节点为"节点10"(数据为10的节点);"节点10"的后继节点是"节点20"(数据为10的节点),"节点20"的前继节点是"节点10";"节点20"的后继节点是"节点30","节点30"的前继节点是"节点20";...;末尾节点的后继节点是表头。


双链表删除节点

双链表添加节点

LinkedList源码分析:

package java.util;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.lang.reflect.Array;

/**
 * @since 1.2
 */
public class LinkedList extends AbstractSequentialList implements
        List, Deque, Queue, Cloneable, Serializable {

    private static final long serialVersionUID = 876323262645176354L;
    
    //LinkedList中的元素的数量
    transient int size = 0;
    
    //双链表中的head,它是空的,不保存数据
    transient Link voidLink;
    
    //LinkedList中的节点,用来保存数据,
    //每个节点包含向前 向后的节点的引用以及本节点的数据
    private static final class Link {
        ET data;

        Link previous, next;

        Link(ET o, Link p, Link n) {
            data = o;
            previous = p;
            next = n;
        }
    }
    
    
    //LinkedList内部的iterator实现,可以用来进行遍历以及数据的增删修改
    private static final class LinkIterator implements ListIterator {
        int pos, expectedModCount;

        final LinkedList list;
        
        //当前节点 最后节点的引用
        Link link, lastLink;
        
        //从指定位置返回LinkedList的iterator
        LinkIterator(LinkedList object, int location) {
            list = object;
            expectedModCount = list.modCount;
            
            //检查角标是否越界
            if (location >= 0 && location <= list.size) {
                // pos ends up as -1 if list is empty, it ranges from -1 to
                // list.size - 1
                // if link == voidLink then pos must == -1
                
                //获取LinkedList的head节点
                link = list.voidLink;
                
                //根据指定位置判断其位于LinkedList前半部分还是后半部分,
                //然后决定是从开始查找,还是从后开始查找,
                //找到指定位置的节点。
                //这种根据位置来决定从前半部分还是后半部分查找的方法在LinkedList中很常见也很有效
                if (location < list.size / 2) {
                    for (pos = -1; pos + 1 < location; pos++) {
                        link = link.next;
                    }
                } else {
                    for (pos = list.size; pos >= location; pos--) {
                        link = link.previous;
                    }
                }
            } else {
                throw new IndexOutOfBoundsException();
            }
        }
        
        //通过iterator添加元素
        
        public void add(ET object) {
            if (expectedModCount == list.modCount) {
                Link next = link.next;//获取当前节点的下一个节点
                //为需要添加的新元素创建一个新的节点对象
                //新节点的前一个节点指向当前节点
                //新节点的后一个节点指向当前节点的原来的后一节点
                //即将新的节点插入原节点于其后一节点之间
                Link newLink = new Link(object, link, next);
                link.next = newLink;//将当前节点的下一个节点指向新建的节点
                next.previous = newLink;//将原节点的后一节点的向前的引用指向新的节点
                link = newLink;//将原节点的引用指向新添加的节点
                lastLink = null;//将原来最后一个节点的引用释放,因为位置发生改变
                pos++;          //指针位置移动
                expectedModCount++;//预期修改次数加一
                list.size++;        //LinkedList元素数量加一
                list.modCount++;    //LinkedList修改次数加一
            } else {
                throw new ConcurrentModificationException();
            }
        }
        
        //返回当前指针位置后面是否还有元素
        //如果该节点后面是head节点,则其为LinkedList最后一个节点
        //否则后面还有其他元素
        public boolean hasNext() {
            return link.next != list.voidLink;
        }
        
        //返回当前指针位置前面是否还有元素
        //如果当前节点不是head节点那么其前面还有元素
        public boolean hasPrevious() {
            return link != list.voidLink;
        }
        
        //获取当前指针位置后面的节点中的元素
        public ET next() {
            if (expectedModCount == list.modCount) {//fail-fase判断
                LinkedList.Link next = link.next;//获取当前阶段的下一节点
                if (next != list.voidLink) {//判断是否已经到末尾
                    lastLink = link = next;//更新引用,向前移动
                    pos++;                  //指针位置向前移动
                    return link.data;       //返回数据
                }
                throw new NoSuchElementException();
            }
            throw new ConcurrentModificationException();
        }
    
    
        //返回下一角标,即指针位置加一
        //指针开始位置为-1,角标开始为0
        public int nextIndex() {
            return pos + 1;
        }
        
        //返回当前指针位置的前一个元素
        public ET previous() {
            if (expectedModCount == list.modCount) {
                if (link != list.voidLink) {
                    lastLink = link;
                    link = link.previous;
                    pos--;
                    return lastLink.data;
                }
                throw new NoSuchElementException();
            }
            throw new ConcurrentModificationException();
        }
        
        //返回当前指针位置的前一角标,即指针本身位置
        //因为指针总是在角标的前一位
        public int previousIndex() {
            return pos;
        }


        //移除LinkedList的一个元素
        public void remove() {
            if (expectedModCount == list.modCount) {
                if (lastLink != null) {
                    Link next = lastLink.next;
                    Link previous = lastLink.previous;//获取lastLink前后节点引用
                    next.previous = previous;
                    previous.next = next;//将lastLink前后节点连接起来
                    if (lastLink == link) {
                        pos--;          //如果移除的是最后一个节点,指针位置减一
                    }
                    link = previous;
                    lastLink = null;
                    expectedModCount++;
                    list.size--;
                    list.modCount++;
                } else {
                    throw new IllegalStateException();
                }
            } else {
                throw new ConcurrentModificationException();
            }
        }
        
        //修改lastLink节点的值
        public void set(ET object) {
            if (expectedModCount == list.modCount) {
                if (lastLink != null) {
                    lastLink.data = object;
                } else {
                    throw new IllegalStateException();
                }
            } else {
                throw new ConcurrentModificationException();
            }
        }
    }

    //倒序的iterator
    private class ReverseLinkIterator implements Iterator {
        private int expectedModCount;

        private final LinkedList list;

        private Link link;

        private boolean canRemove;

        ReverseLinkIterator(LinkedList linkedList) {
            list = linkedList;
            expectedModCount = list.modCount;
            link = list.voidLink;
            canRemove = false;
        }

        public boolean hasNext() {
            return link.previous != list.voidLink;
        }

        public ET next() {
            if (expectedModCount == list.modCount) {
                if (hasNext()) {
                    link = link.previous;
                    canRemove = true;
                    return link.data;
                }
                throw new NoSuchElementException();
            }
            throw new ConcurrentModificationException();

        }

        public void remove() {
            if (expectedModCount == list.modCount) {
                if (canRemove) {
                    Link next = link.previous;
                    Link previous = link.next;
                    next.next = previous;
                    previous.previous = next;
                    link = previous;
                    list.size--;
                    list.modCount++;
                    expectedModCount++;
                    canRemove = false;
                    return;
                }
                throw new IllegalStateException();
            }
            throw new ConcurrentModificationException();
        }
    }
    
    
    //默认的LinkedList构造函数
    //创建一个head节点,其前后节点的引用都指向自己
    //为空
    public LinkedList() {
        voidLink = new Link(null, null, null);
        voidLink.previous = voidLink;
        voidLink.next = voidLink;
    }

    //使用一个collection创建一个LinkedList
    //将collection中所有元素添加到LinkedList中
    public LinkedList(Collection collection) {
        this();
        addAll(collection);
    }

    //添加元素到指定位置
    @Override
    public void add(int location, E object) {
        if (location >= 0 && location <= size) {
            Link 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 previous = link.previous;
            Link newLink = new Link(object, previous, link);
            previous.next = newLink;
            link.previous = newLink;
            size++;
            modCount++;
        } else {
            throw new IndexOutOfBoundsException();
        }
    }

    //默认添加元素,添加到末尾
    @Override
    public boolean add(E object) {
        return addLastImpl(object);
    }
    
    private boolean addLastImpl(E object) {
        Link oldLast = voidLink.previous;
        Link newLink = new Link(object, oldLast, voidLink);
        voidLink.previous = newLink;
        oldLast.next = newLink;
        size++;
        modCount++;
        return true;
    }

    //添加一个collection中的所有元素到LinkedList中,从指定位置开始
    //添加的元素顺序为原collection中的顺序
    @Override
    public boolean addAll(int location, Collection collection) {
        if (location < 0 || location > size) {
            throw new IndexOutOfBoundsException();
        }
        int adding = collection.size();
        if (adding == 0) {
            return false;
        }
        Collection elements = (collection == this) ?
                new ArrayList(collection) : collection;

        Link previous = voidLink;
        if (location < (size / 2)) {
            for (int i = 0; i < location; i++) {
                previous = previous.next;
            }
        } else {
            for (int i = size; i >= location; i--) {
                previous = previous.previous;
            }
        }
        Link next = previous.next;
        for (E e : elements) {
            Link newLink = new Link(e, previous, null);
            previous.next = newLink;
            previous = newLink;
        }
        previous.next = next;
        next.previous = previous;
        size += adding;
        modCount++;
        return true;
    }

    
    @Override
    public boolean addAll(Collection collection) {
        int adding = collection.size();
        if (adding == 0) {
            return false;
        }
        Collection elements = (collection == this) ?
                new ArrayList(collection) : collection;

        Link previous = voidLink.previous;
        for (E e : elements) {
            Link newLink = new Link(e, previous, null);
            previous.next = newLink;
            previous = newLink;
        }
        previous.next = voidLink;
        voidLink.previous = previous;
        size += adding;
        modCount++;
        return true;
    }

    //添加元素到队列的头部 双端链表的方法
    public void addFirst(E object) {
        addFirstImpl(object);
    }

    private boolean addFirstImpl(E object) {
        Link oldFirst = voidLink.next;
        Link newLink = new Link(object, voidLink, oldFirst);
        voidLink.next = newLink;
        oldFirst.previous = newLink;
        size++;
        modCount++;
        return true;
    }

    //添加元素到列表的末尾 
    public void addLast(E object) {
        addLastImpl(object);
    }

    //清空列表
    //将head的前后引用指向自身
    @Override
    public void clear() {
        if (size > 0) {
            size = 0;
            voidLink.next = voidLink;
            voidLink.previous = voidLink;
            modCount++;
        }
    }

    //clone方法
    //复制一个LinkedList然后将当前list加入复制的列表汇中
    @SuppressWarnings("unchecked")
    @Override
    public Object clone() {
        try {
            LinkedList l = (LinkedList) super.clone();
            l.size = 0;
            l.voidLink = new Link(null, null, null);
            l.voidLink.previous = l.voidLink;
            l.voidLink.next = l.voidLink;
            l.addAll(this);
            return l;
        } catch (CloneNotSupportedException e) {
            throw new AssertionError(e);
        }
    }

    //查找列表中是否包含某个元素
    //遍历列表
    @Override
    public boolean contains(Object object) {
        Link link = voidLink.next;
        if (object != null) {
            while (link != voidLink) {
                if (object.equals(link.data)) {
                    return true;
                }
                link = link.next;
            }
        } else {
            while (link != voidLink) {
                if (link.data == null) {
                    return true;
                }
                link = link.next;
            }
        }
        return false;
    }
    
    //获取指定位置的元素
    //熟悉的根据指定的位置来判断从前端还是后端进行遍历
    //从中可以看出,根据角标来获取LinkedList的时候,由于每次
    //都需要进行遍历,因此效率较低
    //严禁通过这种随机访问的形式来进行LinkedList的遍历
    @Override
    public E get(int location) {
        if (location >= 0 && location < size) {
            Link 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();
    }

    //返回队列的首元素
    public E getFirst() {
        return getFirstImpl();
    }

    private E getFirstImpl() {
        Link first = voidLink.next;
        if (first != voidLink) {
            return first.data;
        }
        throw new NoSuchElementException();
    }

    //返回列队的末元素
    public E getLast() {
        Link last = voidLink.previous;
        if (last != voidLink) {
            return last.data;
        }
        throw new NoSuchElementException();
    }
    
    
    //查找指定元素的角标
    @Override
    public int indexOf(Object object) {
        int pos = 0;
        Link link = voidLink.next;
        if (object != null) {
            while (link != voidLink) {
                if (object.equals(link.data)) {
                    return pos;
                }
                link = link.next;
                pos++;
            }
        } else {
            while (link != voidLink) {
                if (link.data == null) {
                    return pos;
                }
                link = link.next;
                pos++;
            }
        }
        return -1;
    }

    //倒序查找指定元素的角标
    @Override
    public int lastIndexOf(Object object) {
        int pos = size;
        Link link = voidLink.previous;
        if (object != null) {
            while (link != voidLink) {
                pos--;
                if (object.equals(link.data)) {
                    return pos;
                }
                link = link.previous;
            }
        } else {
            while (link != voidLink) {
                pos--;
                if (link.data == null) {
                    return pos;
                }
                link = link.previous;
            }
        }
        return -1;
    }

    //返回一个List的iterator
    @Override
    public ListIterator listIterator(int location) {
        return new LinkIterator(this, location);
    }

    //移除指定位置的元素
    @Override
    public E remove(int location) {
        if (location >= 0 && location < size) {
            Link 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 previous = link.previous;
            Link next = link.next;
            previous.next = next;
            next.previous = previous;
            size--;
            modCount++;
            return link.data;
        }
        throw new IndexOutOfBoundsException();
    }
    
    //移除指定元素
    @Override
    public boolean remove(Object object) {
        return removeFirstOccurrenceImpl(object);
    }

    //移除队列的首元素
    public E removeFirst() {
        return removeFirstImpl();
    }

    private E removeFirstImpl() {
        Link first = voidLink.next;
        if (first != voidLink) {
            Link next = first.next;
            voidLink.next = next;
            next.previous = voidLink;
            size--;
            modCount++;
            return first.data;
        }
        throw new NoSuchElementException();
    }

    //移除队列的末元素
    public E removeLast() {
        return removeLastImpl();
    }

    private E removeLastImpl() {
        Link last = voidLink.previous;
        if (last != voidLink) {
            Link previous = last.previous;
            voidLink.previous = previous;
            previous.next = voidLink;
            size--;
            modCount++;
            return last.data;
        }
        throw new NoSuchElementException();
    }

    //返回一个倒序的iterator
    public Iterator descendingIterator() {
        return new ReverseLinkIterator(this);
    }

    //Deque接口的方法实现 添加元素到队列首位
    public boolean offerFirst(E e) {
        return addFirstImpl(e);
    }

    //Deque接口的方法实现,添加元素到队列末位
    public boolean offerLast(E e) {
        return addLastImpl(e);
    }

    //Deque接口的方法实现,获取队列首位的元素
    //队列为空则返回null
    public E peekFirst() {
        return peekFirstImpl();
    }

    //Deque接口方法,获取队列末位元素
    //队列为空则返回null
    public E peekLast() {
        Link last = voidLink.previous;
        return (last == voidLink) ? null : last.data;
    }

    //Deque接口方法
    //移除队列首位元素并返回
    //队列为空则返回null
    public E pollFirst() {
        return (size == 0) ? null : removeFirstImpl();
    }

   //Deque方法
   //移除队列末位元素并返回
    public E pollLast() {
        return (size == 0) ? null : removeLastImpl();
    }

    //Deque方法
    //移除队列首位元素并返回
    //与pollFirst方法区别在于队列为空时会抛出异常
    public E pop() {
        return removeFirstImpl();
    }

    //Deque方法
    //添加元素到队列首位
    public void push(E e) {
        addFirstImpl(e);
    }

    //Deque方法
    public boolean removeFirstOccurrence(Object o) {
        return removeFirstOccurrenceImpl(o);
    }

    
    public boolean removeLastOccurrence(Object o) {
        Iterator iter = new ReverseLinkIterator(this);
        return removeOneOccurrence(o, iter);
    }

    private boolean removeFirstOccurrenceImpl(Object o) {
        Iterator iter = new LinkIterator(this, 0);
        return removeOneOccurrence(o, iter);
    }

    private boolean removeOneOccurrence(Object o, Iterator iter) {
        while (iter.hasNext()) {
            E element = iter.next();
            if (o == null ? element == null : o.equals(element)) {
                iter.remove();
                return true;
            }
        }
        return false;
    }

    //修改指定位置的元素
    @Override
    public E set(int location, E object) {
        if (location >= 0 && location < size) {
            Link 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 int size() {
        return size;
    }
    
    //添加元素到队列末位
    public boolean offer(E o) {
        return addLastImpl(o);
    }
    
    //移除并返回队列首位元素
    public E poll() {
        return size == 0 ? null : removeFirst();
    }
    
    //移除并返回队列首位元素
    //为空时会抛出异常
    public E remove() {
        return removeFirstImpl();
    }
    
    //返回队列首位元素
    //不会删除元素
    //为空时会返回null
    public E peek() {
        return peekFirstImpl();
    }

    private E peekFirstImpl() {
        Link first = voidLink.next;
        return first == voidLink ? null : first.data;
    }
    
    //获取首位元素
    public E element() {
        return getFirstImpl();
    }

    //返回列表的数组形式
    @Override
    public Object[] toArray() {
        int index = 0;
        Object[] contents = new Object[size];
        Link link = voidLink.next;
        while (link != voidLink) {
            contents[index++] = link.data;
            link = link.next;
        }
        return contents;
    }

    //返回列表的数组形式
    //如果参数传递的数组够大则使用参数数组
    //否则创建新数组
    @Override
    @SuppressWarnings("unchecked")
    public  T[] toArray(T[] contents) {
        int index = 0;
        if (size > contents.length) {
            Class ct = contents.getClass().getComponentType();
            contents = (T[]) Array.newInstance(ct, size);
        }
        Link link = voidLink.next;
        while (link != voidLink) {
            contents[index++] = (T) link.data;
            link = link.next;
        }
        if (index < contents.length) {
            contents[index] = null;
        }
        return contents;
    }
    
    //序列化方法
    //先写入容量即size
    //再写入每个节点
    private void writeObject(ObjectOutputStream stream) throws IOException {
        stream.defaultWriteObject();
        stream.writeInt(size);
        Iterator it = iterator();
        while (it.hasNext()) {
            stream.writeObject(it.next());
        }
    }
    
    //反序列化方法
    //先读取容量即size
    //再创建LinkedList,读取每个节点加入队列
    @SuppressWarnings("unchecked")
    private void readObject(ObjectInputStream stream) throws IOException,
            ClassNotFoundException {
        stream.defaultReadObject();
        size = stream.readInt();
        voidLink = new Link(null, null, null);
        Link link = voidLink;
        for (int i = size; --i >= 0;) {
            Link nextLink = new Link((E) stream.readObject(), link, null);
            link.next = nextLink;
            link = nextLink;
        }
        link.next = voidLink;
        voidLink.previous = link;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值