Java 源码系列 1——ArrayList
本文简单介绍了 ArrayList
,并对扩容,添加,删除操作的源代码做分析。能力有限,欢迎指正。
ArrayList是什么?
ArrayList
就是数组列表,主要用来装载数据。底层实现是数组 Object[] elementData
,当我们装载的是基本数据类型 int, long, boolean, shot...的时候我们只能存储他们对应的包装类型。
与它类似的是 LinkedList
,和 LinkedList
相比,它的查找和访问元素的速度较快,但新增,删除的速度较慢。
线程安全吗?
线程不安全。
正常使用场景中,ArrayList
都是用来查询,不会涉及太频繁的增删,如果涉及频繁的增删,可以使用 LinkedList
。如果需要线程安全就使用 Vector
。
Vector
是 ArrayList
的线程安全版本,实现方式就是在所有方法加上synchronized
,性能较差。
如何扩容?
因为数组的大小是固定,当容量超出了现有数组的大小,就需要进行扩容。
为什么说ArrayList插入效率低?
原因有两点:
新增就要检测容量够不够,如果不够就需要扩容
尾部新增比较快,如果是在数组头部或者中部新增就会慢很多,因为要把后面的元素全部往后移一位
把元素往后移一位使用的是复制
System.arraycopy()
,它是native
方法(java定义了接口,其他语言进行实现),所以比较快
删除元素效率如何?
效率和新增差不多,都是要移动元素,但是不需要检查容量和扩容。
适合做队列吗?
非常不适合。
队列是FIFO,在尾巴进,头部出,出的时候需要移动后面所有数据,效率很低。链表比较适合做队列。
new ArrayList<>(18) 会不会初始化数组大小?
不会初始化数组大小!!!
这是Java Bug。
而且将构造函数与initialCapcity结合使用,然后使用set()方法会抛出异常。
总结
底层实现是数组
Object[] elementData
查找和访问元素的速度较快,但新增,删除的速度较慢
线程不安全
每次扩容原有数组大小的一半
源码系列文章
Java源码系列4——HashMap扩容时究竟对链表和红黑树做了什么?
本文首发于我的个人博客 https://chaohang.top
作者张小超
转载请注明出处
欢迎关注我的微信公众号 【超超不会飞】,获取第一时间的更新。
版权声明: 本文为 InfoQ 作者【超超不会飞】的原创文章。
原文链接:【http://xie.infoq.cn/article/d65078126064fe14faff2be44】。文章转载请联系作者。
评论