要分析Arraylist,我们首先要从它的底层数据结构实现出发,再结合其底层源码,可能能让读者理解的更加深刻一点。
1,底层数据结构(数组)
Arraylist底层是基于动态数组实现的。
数组是一种使用连续储存空间储存相同数据类型的线性数据结构。
面试题1
为什么数组索引从0开始不从1开始?
分析:要回答这个问题,我们首先要了解一个知识点,即数组的寻址公式。
解释一下当中的变量,baseAddress:为数组的首地址,i即为寻址为数组中的第几个元素(索引),dataTypeSize即为当前数组对应数据结构的字节数。
如果数组索引从1开始,意味着寻址公式会发生变化。
意味着相比于未发生变化的寻址公式,每次计算机CPU都需要多执行一次i-1操作。
但是次数一多,成千上万,上百万千万后,对执行速度还是有影响。所以归纳出标准答案。
标准答案:
2,ArrayList源码分析
1,ArrayList源码分析-成员变量
private static final int DEFAULT_CAPACITY = 10;
//默认初始的容量
private static final Object[] EMPTY_ELEMENTDATA = {};
//用于空实例的数组实例
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
//用于默认大小空实例的共享空数组实例。
transient Object[] elementData;
//存储ArrayList元素的数组缓冲区。ArrayList的容量是这个数组的长度。
private int size;
//ArrayList的大小(它包含的元素数量)
我们一般关注ArrayList源码中这五个成员变量,后面解释源码的时候会用到。
2,ArrayList源码分析-构造方法
1,无参构造方法
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
读者看到这个elementData有没有很熟悉,没错就是成员变量中的存储ArrayList元素的数组缓冲区,后面这个常量就是默认大小的空数组实例,即调用空参构造方法会创建一个长度为零的数组赋给arrayList。
2,有参构造方法
1,传入INT指定长度
public ArrayList(int initialCapacity) {
if (initialCapacity > 0) {
this.elementData = new Object[initialCapacity];
//如果传入一个INT大于零,则创建该对应整形长度大小的数组
// 赋给arraylist中的elementData
} else if (initialCapacity == 0) {
this.elementData = EMPTY_ELEMENTDATA;
//如果传入一个INT等于零,则将常量EMPTY_ELEMENTDATA(空实例的数组实例)
//赋给arraylist中的elementData
} else {
throw new IllegalArgumentException("Illegal Capacity: " +
initialCapacity);
//其它情况则是传入一个INT小于零,当然是不被允许的,所以抛出异常
}
}
2,传入集合
public <E> ArrayList(Collection<? extends E> c) {
elementData = c.toArray();
//toArray方法即将对象c转为数组
if ((size = elementData.length) != 0) {
// c.toArray 可能并没有返回一个object对象,因此要做出判断
if (elementData.getClass() != Object[].class)
//传入的属性不为Object,调用Arrays.copyOf方法,将Object属性拷贝后转为数组
// 再赋值给elementData
elementData = Arrays.copyOf(elementData, size, Object[].class);
} else {
// c.toArray()是空的,转为空实例的数组实例,赋值给elementData
this.elementData = EMPTY_ELEMENTDATA;
}
}
面试题2,ArrayList list = new ArrayList<>(10)中list扩容几次?
分析:读者可以很轻易看出来,该程序调用了ArrayList 中的有参构造方法中的传入INT指定长度的方法,执行以下逻辑,if (initialCapacity > 0) { this.elementData = new Object[initialCapacity];},创建该对应整形长度大小的数组, 赋给arraylist中的elementData,并未进行扩容。
参考答案:该语句只是声明和实例了一个ArrayList,指定了容量为10,并未进行扩容。
下一篇文章再和大家阅读关于ArrayList扩容,以及添加元素的源码。
标签:实例,面试题,Object,构造方法,ArrayList,elementData,源码,数组 From: https://blog.csdn.net/weixin_52469927/article/details/142834434