ArrayList、LinkedList、Vector的区别
ArrayList:
- 不是线程安全的
- 在该ArrayList对象中,有两个长度,该数组的长度(size,为全局变量),容量(minCapacity,为局部变量),容量不小于长度
- Java8中在new的时候,没有初始化大小,而是在第一次add时,初始化大小为10(指容量,此时的size为1),扩容时,通过Arrays.copyOf()将原来的元素复制到新的容量的数组中
- 在add数据时,如果当前容量小于等于长度,即不够用,会将当前容量的值右移一位(>>1,即除以2),然后相加,变为原来的1.5倍
- 长度最大为Integer.MAX_VALUE-8,是因为在VM中,数组也是一个对象,需要保证一些对象的头信息,这些信息占用的大小最大为8字节,这样不会出现OOM,保证数组的正常使用,但是如果容量还是大于这个值,则可以将容量设置为Integer.MAX_VALUE,这样就不保证程序的正常运行
- 在做增删改查的时候,用的是Arrays.copyOf(),最终用的都是System.arraycopy(),该方法为native方法,如果在做数组操作时,建议用这个方法
- 在ArrayList中,有一个来自AbstractList类的private属性modCount,在对ArrayList进行add和remove操作时,都会对这个属性+1,目的是保证在添加或删除元素时,ArrayList没有其他线程进行操作,即保证并行修改的安全,也就是用于迭代的快速失败
建议&特点:
- 线程不安全
- 底层实现用的基本是native方法System.arraycopy()
- 允许元素有null、可以重复,因为根据插入的顺序来排序的
- 添加(部分快):如果不扩容快,因为是直接往数组最后面添加;如果扩容,需要把原来的所有数据复制到扩容后的数组中,然后再往最后添加,因此建议在初始化时指定大小
- 删除慢(下标),因为要把删除点以后的所有数据复制并移动1位
- 删除慢(对象),因为要先根据for循环查找到对象所在的下标,然后根据下标把删除点以后的所有数据复制并移动1
- 插入快,因为是根据下标,先取数,然后替换,返回旧值
- 查询快,因为是通过数组的下标取数
- 在删除元素时,ArrayList的remove()会将数组中最后一个元素置为null,保证GC的正确使用,所以不必手动=null
- 在删除某个匹配的元素时,最好通过迭代器循环和删除,而不是直接通过foreach循环和删除(虽然foreach也可以,但是,如果要删除的元素在末尾,则会抛出ConcurrentModificationException
Vector:
- 是线程安全的,每个修改list的方法上都有synchronized关键字来保证同步,即保证了某一时刻只能有一个线程来访问其中的方法
- 底层实现和ArrayList一样,都是数组
- 有一个自定义的属性来作为扩容时的增量,如果这个属性没有设置值,则按原来的两倍来扩容
建议:
- 线程安全,仅仅是指多个线程在同时访问Vector中的某个方法时,能保证只有一个线程成功,但如果在多线程中,某个线程里有访问多个方法,且期间有让出CPU的操作(即调用yield()方法),此时,就会出现不同步的情况,所以,如果要想达到多线程访问时的同步效果,最好还是自己在外层添加synchronized关键字来真正保证线程安全
- 如果不是多线程,最好还是使用ArrayList,因为线程同步机制会导致大的系统开销
LinkedList:
- 不是线程安全的
- 只有三个临时变量size(长度)、first(第一个节点)、last(最后一个节点)
- 有一个静态内部类Node,该类作为一个bean来记录节点的三部分内容,即当前节点的前驱、当前节点、当前节点的后继
- 通过new初始化时,没有做任何操作,first和last为null,所以没有初始大小,没有扩容之说
- 在进行add和remove时,是通过修改指定节点的前一个节点和后一个节点的前驱后继来完成
- 在进行get数据时,是通过一次折半来进行循环查找数据
建议:
- 线程不安全
- 对开始、末尾节点操作时非常快,因为有属性first和last
- 如果不是对开始、末尾节点操作,会相对慢一点,因为有一个折半查找节点的方法
- 是有序的,可以有重复
分类 | ArrayList | Vector | LinkedList |
---|---|---|---|
线程 | N | Y(不是绝对安全) | N |
扩容 | 1.5倍(默认10,非初始化) | 2倍(初始化10) | 无 |
长度 | Integer.MAX_VALUE-8 | Integer.MAX_VALUE-8 | 无限制 |
重复 | Y | Y | Y |
null | Y | Y | Y |
有序 | Y | Y | Y |
追加 | 不扩容,快 | 不扩容,快 | 快 |
删除 | 慢(native移动) | 慢(native移动) | 快(折半、循环) |
插入 | 慢(native移动) | 慢(native移动) | 快(折半) |
查询 | 快(下标) | 快(下标) | 慢(循环) |