介绍
ArrayList和LinkedList的使用方法很像,因为他们都实现了List接口,List接口抽象了对集合常见的操作,比如增删查找。但是他们在底层实现上却不一样,所以在使用的时候也有一些点是特别需要注意的。所以我们先简单看看他们的实现。
数据结构
ArrayList底层采用Object数组存储
image.png
因为ArrayList的底层是使用数组存储,所以这个数组的一旦实例化,其大小是不变的,但是ArrayList随着元素添加可以动态变化大小的,于是就无法避免数组的拷贝动作了,我们看看数组的添加方法。
image.png
首先ArrayList方法会先调用ensureCapacityInternal去确认当前数组容量能否容纳新的元素,如果不能则会使用grow方法进行扩容,可以看到这里(下图)是先将数组大小扩展为原来的1.5倍,然后使用Arrays.copy 方法将原来的数组拷贝到新的数组里。
image.png
LinkedList底层采用双向列表实现
image.png
所以在添加新元素的时候要先构造一个Node对象(item为我们加入的值),只需要将Node的next赋值为新的Node即可。
image.png
image.png
所以相对于ArrayList而言,LinkedList可以更加高效的插入元素,因为它不会涉及到ArrayList扩容。但也因为这种数据结构,导致它不具备有随机访问的能力。
总结
1.ArrayList 的插入,删除效率低于LinkedList。
因为ArrayList需要随时进行Object数组容量大小检查,如果数组容量不能满足新插入元素所需要的大小需求,那么就会触发自动扩容,将大小扩展为原来的1.5倍,在将原来的数组拷贝到新的数组中,然后在添加元素,删除元素时也可能会涉及到数组拷贝。而LinkedList在添加元素时仅需要将Node的next指向要添加的元素构造出来的Node即可,删除元素也只涉及到Node指向的改变。
2.ArrayList的可以随机访问指get,set方),但是LinkedList不可以。所以ArrayList的随机访问效率高。
ArrayList底层是数组实现,所以它可以通过数组下标进行访问,只要知道了数组下标就可以立即返回结果。但是LinkedList是链表实现,给定一个索引值就只能通过遍历链表查找元素了。所以在遍历集合时,我们要避免通过随机查找元素的方式来遍历LinkedList。
3.ArrayList和LinkedList都不是线程安全的。
ArrayList和LinkedList 内部都维护了modCount(修改次数),也没有做同步操作,当多个线程同时修改时会比较modCount,当modCount不同时抛出ConcurrentModificationException。
网友评论