ArrayList、LinkedList、CopyOnWriteArrayList和Vector的区别详解

一. Array

Array(数组)是基于索引(index)的数据结构,且它占用的内存空间是连续的,所以搜索和读取数据时使用索引在数组中是很快的。

         Array获取数据的时候非常快,直接通过索引找到数据,时间复杂度是O(1);但是要删除数据却是开销很大,因为删除数据后需要把后面剩下的所有数据前移。

注意:数组初始化必须指定初始化的长度, 否则报错。

eg:

   int[] x = new int[];//报错,没有初始化长度

   int[] x = new int[5];//正确,初始数组长度为5(index范围为0 - 4)

 二. List

List可以包含重复的元素,使用按索引访问的方式,继承于Collection。

        List是一个接口,不可以直接实例化,其中介绍四个重要的实现类:

ArrayList、LinkedList、CopyOnWriteArrayList和Vector。

 

他们的继承关系如下:

 

继承截图:

 

继承结构图:

 

三.ArrayList

ArrayList 可以看作是能够自动增长容量的数组,ArrayList底层的实现是Array,故ArrayList的容量可以扩展,但是需要连续的内存空间。

 

例子:

         ArrayList 的实例ArrayX数组,当前占三个内存资源,数组大小为3,当添加第四个数据时,ArrayX会自动扩容,扩容的过程为:

(1)判断当前数组之后有无连续的内存空间,如有则直接在数组之后扩容然后添加数据;

(2)如果当前数组之后没有可用空间,则往下找,找到能够装下添加数据之后的数组的连续内存空间,然后申请空间,将之前的数组复制到这一块连续的内存空间,然后在这个复制过来的新数组后添加该数据;

(3)将原来的老数组占用的内存空间回收。

 

如下图:

 

说明:ArrayList在初始化的时候指定长度要比不指定长度的性能好很多, 这样不用重复的申请空间, 复制数组, 销毁老的数组。

如下代码,在不断增加数据的过程,2比1执行速度更快。

 public static int length = 1024; 

//1.未指定长度
    List<Integer> list1 = new ArrayList<>();
//2.指定长度
    List<Integer> list2 = new ArrayList<>(length);

 

四.LinkList

LinkList是一个双链表,在get与set方面比ArrayList差,即查找数据时在平均性能上比ArrayList更差,但在添加和删除元素时具有比ArrayList更好的性能。LinkList的存储不需要连续的存储空间。

 

例子:

LinkList 的实例LinkX数组,当前占三个内存资源,链表大小为3,当添加第四个数据时,过程为:

(1)链表不需要连续的空间, 直接找到空闲的内存空间存下数据。

 

如下图:

 

 五.CopyOnWriteArrayList

CopyOnWriteArrayList和 ArrayList一样,也是通过数组实现的,但确是线程安全容器(相对于 ArrayList),增加删除等写操作通过加锁的形式保证数据一致性,通过复制新集合的方式解决遍历迭代的问题。

          CopyOnWriteArrayList的增删改都需要获得锁,并且锁只有一把,而读操作不需要获得锁,支持并发。在增删改的过程中都会创建一个新的数组,操作完成之后再赋给原来的引用,这是为了保证get的时候都能获取到元素,如果在增删改过程直接修改原来的数组,那么可能会造成执行读操作获取不到数据。因此在增删改的过程中都会先创建一个数组。待操作完成之后再将新数组的引用赋值给array。

几个要点

  • CopyOnWriteArrayList内部持有一个ReentrantLock lock = new ReentrantLock();
  • 底层是用volatile transient声明的数组 array
  • 读写分离,写时复制出一个新的数组,完成插入、修改或者移除操作后将新数组赋值给array

 

 六.Vector

        Vector(向量类)与ArrayList一样,也是通过数组实现的,不同的是它支持线程的同步,即某一时刻只有一个线程能够写Vector,避免多线程同时写而引起的不一致性,但实现同步需要很高的花费,因此,访问它比访问ArrayList慢。vector是线程(Thread)同步(Synchronized)的,所以它也是线程安全的,而Arraylist是线程异步(ASynchronized)的,是不安全的。如果不考虑到线程的安全因素,一般用Arraylist效率比较高。

 

 7.总结

1.ArrayList和LinkList的区别:

(1)ArrayList是基于数组的,存储需要连续的存储空间,LinkList是基于链表的,存储不需要连续的存储空间;

(2)如果需要大量的查询数据,使用ArrayList,如果需要大量的增删数据,使用LinkList。

 

2.ArrayList、CopyOnWriteArrayList、Vector的区别:

(1)ArrayList非线程安全的,如果需要考虑到线程安全问题,那么可以使用Vector和CopyOnWriteArrayList;

(2)Vector和CopyOnWriteArrayList的区别是 : 是增删改查方法都加了synchronized,保证同步,但是每个方法执行的时候都要去获得锁,性能就会大大下降,而CopyOnWriteArrayList 只是在增删改上加锁,但是读不加锁,在读方面的性能就好于Vector,CopyOnWriteArrayList支持读多写少的并发情况。

 

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值