LinkedList

说明

List 和 code Deque 接口的双向链表实现。实现所有可选的列表操作,并允许所有元素(包括null)。

所有操作的执行都符合双向链表的预期。索引到列表中的操作将从开始或结束遍历列表,以更接近指定索引的为准。

注意这个实现不是同步的。如果多个线程并发访问一个链表,并且至少有一个线程在结构上修改了链表,它必须在外部同步。 (结构修改是添加或删除一个或多个元素的任何操作;仅设置元素的值不是结构修改。)这通常是通过同步一些自然封装列表的对象来完成的。如果不存在此类对象,则应使用CollectionssynchronizedList Collections.synchronizedList 方法“包装”该列表。这最好在创建时完成,以防止对列表的意外不同步访问: List list = Collections.synchronizedList(new LinkedList(...));

这个类的 返回的迭代器code iterator 和 e listIterator 方法是 fail-fast:如果在创建迭代器后的任何时间以任何方式修改列表的结构,除了通过 Iterator 自己的 remove 或 add 方法,迭代器将抛出一个 ConcurrentModificationException。因此,面对并发修改,迭代器快速而干净地失败,而不是冒着在未来不确定的时间出现任意、非确定性行为的风险。

请注意,无法保证迭代器的快速失败行为,因为一般来说,在存在非同步并发修改的情况下不可能做出任何硬性保证。快速失败的迭代器会尽最大努力抛出 ConcurrentModificationException。因此,编写一个依赖此异常来确保其正确性的程序是错误的:迭代器的快速失败行为应该仅用于检测错误。

源码分析(部分)

  transient int size = 0;

    /**
     * 头结点
     */
    transient Node<E> first;

    /**
     * 尾节点
     */
    transient Node<E> last;

    /**
     * 无参数的构造器
     */
    public LinkedList() {
    }

    /**
     * 带有一个集合参数的构造器
     */
    public LinkedList(Collection<? extends E> c) {
        this();
        addAll(c);
    }

    /**
     * 头插法,就是将e放在链表的第一个
     */
    private void linkFirst(E e) {
        final Node<E> f = first;
        final Node<E> newNode = new Node<>(null, e, f);
        first = newNode;
        if (f == null)
            last = newNode;
        else
            f.prev = newNode;
        size++;
        modCount++;
    }

    /**
     * 尾插法,就是将要放入的元素放在最后一位
     */
    void linkLast(E e) {
        final Node<E> l = last;
        final Node<E> newNode = new Node<>(l, e, null);
        last = newNode;
        if (l == null)
            first = newNode;
        else
            l.next = newNode;
        size++;
        modCount++;
    }
     /**
     * 在固定元素前插入一个元素
     */
    void linkBefore(E e, Node<E> succ) {
        // assert succ != null;
        final Node<E> pred = succ.prev;
        final Node<E> newNode = new Node<>(pred, e, succ);
        succ.prev = newNode;
        if (pred == null)
            first = newNode;
        else
            pred.next = newNode;
        size++;
        modCount++;
    }

    /**
     *取消链接非空的第一个节点 f
     */
    private E unlinkFirst(Node<E> f) {
        // assert f == first && f != null;
        final E element = f.item;
        final Node<E> next = f.next;
        f.item = null;
        f.next = null; // help GC
        first = next;
        if (next == null)
            last = null;
        else
            next.prev = null;
        size--;
        modCount++;
        return element;
    }

    /**
     * 取消链接非空的最后一个节点 f。
     */
    private E unlinkLast(Node<E> l) {
        // assert l == last && l != null;
        final E element = l.item;
        final Node<E> prev = l.prev;
        l.item = null;
        l.prev = null; // help GC
        last = prev;
        if (prev == null)
            first = null;
        else
            prev.next = null;
        size--;
        modCount++;
        return element;
    }

    /**
     * 取消链接非空节点 x。
     */
    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;
    }

    /**
     * 获得链表的第一个元素
     */
    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 E removeFirst() {
        final Node<E> f = first;
        if (f == null)
            throw new NoSuchElementException();
        return unlinkFirst(f);
    }

    /**
     * 移除链表最后一份节点
     */
    public E removeLast() {
        final Node<E> l = last;
        if (l == null)
            throw new NoSuchElementException();
        return unlinkLast(l);
    }

    /**
     * 在头部插入节点
     */
    public void addFirst(E e) {
        linkFirst(e);
    }

    /**
     * 在尾部加入节点
     */
    public void addLast(E e) {
        linkLast(e);
    }

    /**
     *判断链表中是否存在特定元素
     */
    public boolean contains(Object o) {
        return indexOf(o) != -1;
    }

    /**
     *返回链表中元素的数量
     */
    public int size() {
        return size;
    }

    /**
     * 判断在尾部能否添加该元素
     */
    public boolean add(E e) {
        linkLast(e);
        return true;
    }

    /**
     *判断呢能否移除相关元素,返回true表示已经移除
     */
    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;
    }

    /**
     * Appends all of the elements in the specified collection to the end of
     * this list, in the order that they are returned by the specified
     * collection's iterator.  The behavior of this operation is undefined if
     * the specified collection is modified while the operation is in
     * progress.  (Note that this will occur if the specified collection is
     * this list, and it's nonempty.)
     *
     * @param c collection containing elements to be added to this list
     * @return {@code true} if this list changed as a result of the call
     * @throws NullPointerException if the specified collection is null
     */
    public boolean addAll(Collection<? extends E> c) {
        return addAll(size, c);
    }

   

LinkedList总结

  1. LinkedList是一个功能很强大的类,可以被当作List集合,双端队列和栈来使用。
  2. LinkedList底层使用链表来保存集合中的元素,因此随机访问的性能较差,但是插入删除时性能非常的出色。
  3. LinkedList在1.8版本有添加了一点新的内容,添加了一个static final 修饰的内部类LLSpliterator 并实现了Spliterator ,为了实现并行遍历而新添加的功能,整体的变化并不是很大,感兴趣的可以自己去看一下。
  4. List实现类的使用场景
    ArrayList,底层采用数组实现,如果需要遍历集合元素,应该使用随机访问的方式,对于LinkedList集合应该采用迭代器的方式
    如果需要经常的插入。删除操作可以考虑使用LinkedList集合
    如果有多个线程需要同时访问List集合中的元素,开发者可以考虑使用Collections将集合包装成线程安全的集合。
  5. 补充说明
    从源码中很明显可以看出,LinkedList的实现是基于双向循环链表的,且头结点中不存放数据。
    注意两个不同的构造方法。无参构造方法直接建立一个仅包含head节点的空链表,包含Collection的构造方法,先调用无参构造方法建立一个空链表,而后将Collection中的数据加入到链表的尾部后面。
    在查找和删除某元素时,源码中都划分为该元素为null和不为null两种情况来处理,LinkedList中允许元素为null。
    LinkedList是基于链表实现的,因此不存在容量不足的问题,所以这里没有扩容的方法。
    注意源码中的Entry entry(int index)方法。该方法返回双向链表中指定位置处的节点,而链表中是没有下标索引的,要指定位置出的元素,就要遍历该链表,从源码的实现中,我们看到这里有一个加速动作。源码中先将index与长度size的一半比较,如果index<size/2,就只从位置0往后遍历到位置index处,而如果index>size/2,就只从位置size往前遍历到位置index处。这样可以减少一部分不必要的遍历,从而提高一定的效率(实际上效率还是很低)。
    注意链表类对应的数据结构Entry。
    LinkedList是基于链表实现的,因此插入删除效率高,查找效率低(虽然有一个加速动作)。
    要注意源码中还实现了栈和队列的操作方法,因此也可以作为栈、队列和双端队列来使用。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值