自我介绍篇
大家好,我是你们的会飞翔的蜗牛。看源码,就像打怪升级,作为我开始作为新手练级的一个boss就是ArrayList。那么出发打怪咯。
第一个BOSS
俗话说,知已知彼,方能百战不殆。那么我们先来了解下BOSS吧。它底层其实也是一个数组,所以我们也经常叫它动态数组。如果你看过我第一章节,你应该知道我在源码杂谈中,其实已经总结了学习源码集合的经验。我总结了所有源码集合中的共性的一些特性,并最终提炼出一些学习的方法。
装备自己
集合的共有特性有哪些?
1,组成集合最简单的数据结构是哪些?
2,集合默认初始化的长度是多少?
3,集合是否显示设置了扩容的因子?如果没设置?那么扩容因子多大?
4,集合的扩容最大值设置了多少?
5,集合的增删改查的细节了解多少?
6,集合扩容的条件是什么?怎么进行扩容的?有哪些细节需要注意的?
7,集合的查询的时间复杂度?新增元素的时间复杂度?
8,集合创建的时机,是new生成,还是add得时候生成?
9,集合是否线程安全?如果不是,如果保证线程安全?如果是,基于怎么样的原理?
10,相比较其他集合,它有什么优点和缺点?
说了这么多,我觉得你已经开始头晕了,没错,我只是列举了一些问题,希望你能带着这些问题,开始去看源码,而不是无头苍蝇一般这里看点,那里看点,最后不知道自己是否真的理解了集合。
打怪升级
学习本身就是一件枯燥得事情。如果你能把源码学习,学出乐趣出来。那么生活真的很精彩。好像在夸自己一样,O(∩_∩)O。
争对上面得问题,我们怎么去攻克我们得第一关得BOSS
1,ArrayList底层是一个数组。不信你看
private static final Object[] EMPTY_ELEMENTDATA = {};
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
transient Object[] elementData
ps:说好不贴代码的,男人的嘴骗人的鬼,哈哈,为了节省你找代码的时间。O(∩_∩)O。
2,ArrayList的默认初始长度是10。
private static final int DEFAULT_CAPACITY = 10;
3,ArrayList的扩容因子是1.5倍。并没有显示得设置一个属性,而从代码出能看出来。
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
//扩容成原来的1.5倍大小
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);
}
4,ArrayList的最大值
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
5,集合的增删改查
这里不细细地讲了,但是对于新增和删除地某些细节,我这里特别指出来。
- 新增元素。add地时候会先去判断整个集合是否已经塞不下元素了。那么就可以开始扩容了。那么可能出现两种情况,如果没有超出最大值,那么按照之前讲的,把集合大小扩容到1.5倍。如果超出了最大值,那么抛出异常。
- 删除元素。删除元素有一个细节很重要。删除元素主要是调用了下面一个方法。
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
// clear to let GC do its work(翻译:让GC去回收掉内存)
elementData[--size] = null;
arracycopy大体可以理解为,把删除元素的索引为起点,右边的所有元素往左平移一格。最后的元素赋值为null,便于gc回收。
总结:
- ArrayList是动态数组。
- 默认初始长度为10,容量不够,每次以1.5倍增长。
- 线程不安全。
- 在new的时候创建一个空数组。当第一次add的时候,会设置长度为默认长度10。
- 在尾部删除,增加元素的时间复杂度为O(1)。在中间删除,增加元素的时间复杂度为O(n)。随机查询的时间复杂度为O(1)。
好了,今天的分享就到此结束了,感谢各位大佬的围观,我尽量增加趣味性地去讲清楚ArrayList底层实现。但是学习总是枯燥地,任何思考,都需要抛开娱乐,静下心来。就好像得道高僧,总是要放下执念,才能遁入佛道。高僧–>和尚–>秃头–>程序猿,O(∩_∩)O