LinkedList笔记&ArrayList和LinkedList的区别

LinkedList简介

LinkedList 是一个继承于AbstractSequentialList的双向链表。它也可以被当作堆栈、队列或双端队列进行操作。
LinkedList 实现 List 接口,能对它进行队列操作。 LinkedList 实现 Deque接口,即能将LinkedList当作双端队列使用。
LinkedList 实现了Cloneable接口,即覆盖了函数clone(),能克隆。
LinkedList 实现java.io.Serializable接口,这意味着LinkedList支持序列化,能通过序列化去传输。
LinkedList 是非同步的。
LinkedList 是有序的。
LinkedList 集合中元素允许为 null
在这里插入图片描述
LinkedList 允许存入重复的数据

在这里插入图片描述
LinkedList在内存中开辟的内存不连续【ArrayList开辟的内存是连续的】

在这里插入图片描述
头结点和尾节点并没有关联起来【头节点的prev指向null、尾节点的next指向的也是null】,所以跟循环双向链表区别开来。

因为是双向链表结构,所以要删除数据时,直接将【删除节点】的首尾引用指向null,让【删除节点】的【上一个节点】的next引用指向【删除节点】的【下一个节点】,同理,【下一个节点】的prev引用指向【上一个节点】
同理,新增数据也一样,【新增节点】的首尾引用分表指向【上一个节点】和【被插入节点】,再将【加粗样式上一个节点】的next引用指向【新增节点】,【被插入节点】的prev引用指向【新增节点】
查询数据慢的原因就在于它不是连续的,所以你没法像ArrayList一样get(index)快速获取数据,它需要在链表上一个个查询,直到找到你要的数据。

LinkedList分析

LinkedList是通过从header开始index计为0,然后一直往下遍历(next),直到到index位置。为了优化查询效率,LinkedList采用了二分查找(这里说的二分只是简单的一次二分),判断index与size中间位置的距离,采取从header向后还是向前查找。
到这里我们明白,基于双向循环链表实现的LinkedList,通过索引Index的操作是低效的,index所对应的元素越靠近中间所费时间越长。而向链表两端插入和删除元素则是非常高效的(如果不是两端的话,都需要对链表进行遍历查找)。

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

在查找删除增加中全部用到了node(index)

public E get(int index) {
        checkElementIndex(index);
        return node(index).item;
    }
public E set(int index, E element) {
        checkElementIndex(index);
        Node<E> x = node(index);
        E oldVal = x.item;
        x.item = element;
        return oldVal;
    }
 public void add(int index, E element) {
        checkPositionIndex(index);

        if (index == size)
            linkLast(element);
        else
            linkBefore(element, node(index));
    }

(1)LinkedList做插入、删除的时候,慢在寻址,快在只需要改变前后Entry的引用地址

(2)ArrayList做插入、删除的时候,慢在数组元素的批量copy,快在寻址

ArrayList和LinkedList的区别

从实现看:

LinkedList底层实现是双链表
ArrayList底层实现是动态数组
从扩容机制看:

LinkedList不存在扩容 的说法,因为是链表结构。
ArrayList底层是动态数组存在扩容说法,默认的数组大小是10,在检测是否需要扩容后,如果扩容,会扩容为原来的1.5倍大小。原理就是把老数组的元素存储到新数组里面
从优点看:

ArrayList的查找性能好,因为底层是数组,适用于查找元素。
LinkedList底层是双链表,对于插入或者删除元素来说,操作方便,性能高。
从缺点看:

ArrayList因为是一块连续的内存,存储数据元素,所以如果要删除或者插入一个元素,那么之前或者之后的元素都要移动,代价很高。
LinkedList是链表,在内存中可以是不连续的,通过指针连接结点,如果要查找元素,必须去遍历整个链表,这样就比较麻烦。
从安全角度看:

ArrayList在单线程环境下是安全的,多线程环境下不是线程安全的,容易造成脏读的问题,如果要使ArrayList是线程安全的,那么可以选择使用Collections.synchronizedList(new ArrayList())
LinkedList在单线程环境下是安全的,多线程环境下不是线程安全的,容易造成脏读的问题,如果要使LinkedList是线程安全的,那么可以选择使用Collections.synchronizedList(new LinkedList())
LinkedList和ArrayList的数据存储都是有序的,而且元素是可以重复的。

两者add都是将元素追加到现有集合元素的末尾。

LinkedList 真的是查找慢增删快?刷新你的认知!
LinkedList以及ArrayList的效率比较

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值