ArrayList总结


前言

学习ArrayList源码的过程中,避免不了需要查询许多的博客,学习一下别人的思想,下面分享一篇博客的总结,只是部分总结性的知识点,详情的话请大家点进去看看这篇文章,强烈推荐!原文链接https://www.cnblogs.com/mfrank/p/9130136.html
如有侵权请联系删除。


一、要点总结

这部分主要根据上面的源码进行说明,如果有不太清楚的地方,可以返回上面的源码进行查看。

1.ArrayList 其实只是内部维护了一个数组,通过暴露出方便操作的接口来简化操作。

2.ArrayList中,size和capacity是两码事,size表示列表中实际存储的元素个数,一般小于内部数组长度,而capacity表示容量,即内部数组的长度。

3.ArrayList中,默认的大小是10,当你使用new ArrayList();时并不会立即为数组分配大小为10的空间,而是等插入第一个元素时才会真正分配,这样做是为了节约内存空间。

4.由于上述目的的存在,为了区分默认列表和空列表,设置了两个空数组常量,EMPTY_ELEMENTDATA和DEFAULTCAPACITY_EMPTY_ELEMENTDATA,这样在扩容时就能进行不同的处理。

5.维护内部数组时,使用的是Arrays.copyOf()方法和System.arraycopy()方法。

6.里面有多处使用modCount,这个变量其实是继承自父类AbstractList,用来标识列表内部数组大小被修改的次数(如add,trimToSize等操作可能会触发),元素的替换并不会改变它的值,迭代器的“fail-fast”机制跟这个modCount变量紧密相关,一般会在操作前赋值一次 expectedModCount = modCount; 在操作执行完之后再进行一次检测,如果仍相等,说明结构未改变,否则将抛出异常,这也就是为什么上一篇中ArrayList修改过之后,操作迭代器会抛出异常的原因。

7.在扩容时,默认的扩容因子是1.5,每次需要扩容时,会将原数组大小的1.5倍和实际需要的数组空间进行比较,从中取最大值作为数组大小。然后新建一个数组,把原数组中的所有元素复制到新数组中去。所以扩容其实是最耗费时间的操作,不仅仅需要重新分配空间,而且需要重新赋值。

8.因为ArrayList的方法操作的都是同一个内部数组,而所有方法都没有加锁,没有同步机制,所以它是线程不安全的。

9.ArrayList中可以存放null值,可以在源码中看到,在比较时对null值都进行了处理。

二、优缺点说明

因为列表其实是内部维护管理着一个数组,所以数组的优点它都具备。当然,数组的缺点它同样也存在。

数组是将元素在内存中连续存放,由于每个元素占用内存相同,可以通过下标迅速访问数组中任何元素。但是如果要在数组中增加一个元素,需要移动大量元素,在内存中空出一个元素的空间,然后将要增加的元素放在其中。同样的道理,如果想删除一个元素,同样需要移动大量元素去填掉被移动的元素。

但是列表在维护这个内部数组时,还是花了一点心思的,比如使用capacity的概念来减少数组结构改变的次数,所以并不会每次add操作都导致结构改变。将扩容因子选为1.5而不是2,也是为了在满足需求的前提下尽可能的节约空间,但如果事先就知道元素的大概个数时,最好先在构造器中设置好列表的容量,这样就可以省掉不少扩容时的开销。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值