提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
- 集合框架的底层原理,在看底层原理使用JDK6版本方便阅读。
- 集合的api一些函数不说明,主要是对于一些细节,以及容易忘的地方进行理解和描述。
- 一定要使用调试的方法,进入到底层查看源代码。
一、集合框架
- Collection<接口>[一个一个]
-
List<接口>[有序可重复]
-
ArrayList<类>[使用数组实现的列表] (也叫动态数组)
-
LinkedList<类>[使用链表实现的列表]
二、源代码解读
代码如下(示例):
public class ArrayListDemo1 {
public static void main(String[] args) {
ArrayList arrayList = new ArrayList(3);
arrayList.add("小乔");
arrayList.add("周瑜");
arrayList.add("诸葛亮");
arrayList.add("曹操");
}
}
one
ArrayList的默认无参构造方法是创建一个长度为10的数组进行元素存储。
two (查看扩容原理)
给定ArrayList的初始容量为3,按照道理只能存储3个元素。
但在存储曹操这个元素的时候,是可以存入的。
源代码中的ensureCapacity()这个方法就是进行扩容
三、异同
JDK6与JDK7、8在此异同
JDK6:
- 无参数构造器创建数组长度容量为10。
添加元素的时候扩容了1.5倍然后将原有数组的数据复制到新的数组中,根据扩容的问题,建议实际开发过程中如果大
概知道存储数据的个数,那么尽量使用指定容量的构造器。
JDK7、8:
- 无参数构造器实际上并没有针对于存储数组进行创建,这样做的目的是为了节约内存空间。
在第一次调用add方法的时候才会针对于数组进行实际的创建(初始容量为10),并且将添加的数据放置在数组的一个
位置上。 - 后续的添加和扩容的操作和JDK无异。
四、总结
ArrayList的扩容原理(动态数组)
- 进行数据存储使用数组的形式
- 扩容不是必然的,首先判断所需的空间对于数组当前的长度是否还满足。不满足则扩容。
- 每次扩容为1.5倍(考虑到内存开销和效率问题)
- StringBuilder每次扩容是2倍,为什么ArrayList相比于StringBuilder扩容倍数相对保守?
-
数据存储类型不同。存储数据大小不同
- 运算出扩容个数之后,为什么还要判断数目够不够?
- ArrayList.addAll(arraylist1) 添加多个元素