ArrayList

1、ArrayList简述
首先,众所周知,ArrayList是一个线程不安全的容器,其底层维护了一个数组,它最大的特点就是按照插入顺序来保存元素,可以利用下标来查找值,因此查询速度十分的快,其缺点也正是因为其数组的特性在中间插入元素很慢、删除下标靠前的元素很慢。
2、ArrayList的构造器
接下来说一说ArrayList的构造器,我们常用的构造函数有两个,分别是有参和无参的,无参的构造函数十分简单,只是初始化了一个空的Object型数组。
再来说有参的,其实参数的含义就是这个集合的容量,也就是说如果我们传入的参数为10,那么ArrayList将会初始化一个长度为10的空的Object型数组,这两个构造器究竟有何区别,接下来才是重点。
3、ArrayList的添加方法
在添加元素之前,会先判断是否声明的是无参构造函数,在这里就显现出了两个构造器的区别了,如果我们一开始声明的是一个空参的构造函数,这是ArrayList就会初始化数组长度为10,试想,如果我们只需要存储3个元素,而我们声明了一个空参的构造函数,那么集合的长度会是10,也就是说,数组有7个长度的空间被浪费了,这就是对内存的一种浪费,所以如果在使用ArrayList时在确认放置元素数量的情况下,再在构造器中传入合适的参数,这样可避免内存的浪费。
接下来会再去需要确保容量是否够用,如果够用,那么不需要扩容,反之,则进行扩容,它是通过Arrays.copyOf(elementData, newCapacity)方法实现扩容的,这个方法需要传入两个参数,一个是原数组,一个是原数组容量1.5倍的一个数值(这是数值是通过原来数组长度经过位移运算向右位移一位+原来长度实现的代码如下:int newCapacity = oldCapacity + (oldCapacity >> 1)),这样就生成一个新的数组,并将原有的数组内容全复制进去。试想一下,我们需要保存1000个元素,而一开始默认长度是10,那么集合需要很多次扩容,每次扩容是上一次容量的1.5倍,每次扩容还要进行复制。如果不事先声明一个长度的话,使用效率会大大降低,即便是不知道具体数字,也可以指定一个大概的容量。这也说明了两个构造器的另一个区别。

4、ArrayList的删除方法
删除是每次进行数组复制,然后将旧的数组置为null进行垃圾回收。
5、ArrayList的插入方法
插入方法类似,也是先进行数组复制,然后将旧的数组置为null进行垃圾回收。
6、File-fast机制
虽然ArrayList是线程不安全的,但为了尽量的提高数据存储的安全性,ArrayList引入了叫做file—fast的快速失败机制。假设存在两个线程(线程1、线程2),线程1通过Iterator在遍历集合A中的元素,在某个时候线程2修改了集合A的结构(是结构上面的修改,而不是简单的修改集合元素的内容),那么这个时候程序就会抛出 ConcurrentModificationException 异常,从而产生fail-fast。Java.util包中的所有集合类都是快速失败的,他们都维护了一个count变量,在查询遍历之前会先获取该变量,如果中途有结构变动,count会自增,这时count与之前不一样,程序立即抛出异常(乐观锁的机制)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值