学习笔记——LinkedList总结

LinkedList底层是一个双向链表。之所以说是双向的,是因为同时维护了当前节点的前节点和后节点。

可以看下节点的结构:

    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;
        }
    }

item就是当前节点的元素,next指向当前节点的后一个节点,prev指向当前节点的前一个节点。

和ArrayList的对比

其实就是链表和数组的对比。

插入,删除:

ArrayList:基于数组实现,通常情况下添加元素很简单,直接将元素添加到预先创建的数组中,没有额外操作。但当数组空间不足时,就涉及到扩容,数组的复制,性能很差。

                  删除时,需要进行数组元素的复制,性能不高。

LinkedList:基于链表实现,可变长,单纯的插入和删除操作,都比较简单,修改下关联节点的前后"指针"即可。

查询:

ArrayList:支持随机访问,查询效率高。时间复杂度O(1)。

LinkedList:不支持随机访问,按下标索引查询效率较低。可以看下源码:  

   Node<E> node(int index) {
        // assert isElementIndex(index);

        if (index < (size >> 1)) {
            Node<E> x = first;
            for (int i = 0; i < index; i++)
                x = x.next;
            return x;
        } else {
            Node<E> x = last;
            for (int i = size - 1; i > index; i--)
                x = x.prev;
            return x;
        }
    }
View Code

LinkedList中涉及到index的方法,基本都是通过这种方式实现的。

在一个长度为n的LinkedList中,查找一个元素平均要查找(1+n/2)/2次,时间复杂度O(n)。如果是循环遍历的话,那复杂度就是O(n^2)。

所以对不支持随机访问的集合类,尽量不要使用下标索引的方式进行元素的遍历,推荐使用迭代器。(这个在RandomAccess接口说明中有提到)

 

posted @ 2018-12-28 10:20  boogieman  阅读(613)  评论(0编辑  收藏  举报