List
ArrayList和LinkedList的区别
底层数据结构的不同,ArrayList是数组,LinkedList是双向链表
两者增删改查的效率各不相同,ArrayList可以根据索引更快的查找,而对于LinkedList来说,增加和删除元素的效率更好
两者都是线程不安全的,对于ArrayList来说,Vector就是其线程安全版本的实现,但是两者的一些实现细节还是略有区别,比如说扩容机制,ArrayList是扩容到原容量的1.5倍,而Vector是扩容到原容量的2倍
ArrayList
底层是数组,transient是一个关键字,只能用来修饰成员变量,表示这个成员变量不能被序列化,那什么时候需要序列化呢?比如一些网络传输的时候我们会把数据序列化传输,这样传输的数据量小

add()
在添加元素之前会先判断是否需要扩容,如果需要扩容,我们会调用grow()函数进行扩容,也可以看到这里有个懒加载的机制,在第一次添加元素的时候ArrayList才会初始化底层的数组(默认容量是10),如果不需要扩容,我们可以直接插入元素

grow()
首先对于数组来说,数组是没有扩容机制的,ArrayList底层实现扩容的方式就是创建一个更大容量的新数组,ArrayList底层的扩容机制默认扩容到原容量的1.5倍,如果初始为0,那么扩容到1;如果初始为1,那么扩容到2,再通过Arrays.copyof() 将旧的数组的每个元素copy过去

remove()
ArrayList在删除元素之前会先检查位置是否合法,然后再删除,需要调用native方法移动数组元素

get()
根据下标直接返回元素

LinkedList
底层是双向链表,有一个头节点以及一个尾节点

每个节点的结构

add()
可以在else分支看到LinkedList使用的是尾插法插入新的节点

remove()
拿到待删除节点的前后节点,进行双向链表那样的删除,也就是将该节点的前驱节点和后继节点连接起来

get(int index)
LinkedList底层会用二分法先优化一下,索引位置和链表长度的一半先比对一下,判断从左半边遍历还是右半边遍历,当然还有getFirst()以及getLast()方法快速的获取头尾节点

本文对比了ArrayList和LinkedList在底层数据结构、增删改查效率、线程安全性以及序列化需求上的差异,特别强调了ArrayList的扩容策略和LinkedList的插入删除操作。
5357





