分析下ArrayList源码,看源码的时候主要从三个方面去翻阅:成员变量,构造函数,关键方法
本地环境(jdk1.8)调试下,实例化一个ArrayList()对象,点击进入源码
类的声明
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
可以看到除了继承自AbstractList类的方法和属性外,ArrayList还实现了List接口、RandomAccess接口、Cloneable接口和Serializable接口,这意味着ArrayList可以被克隆并且支持序列化操作。
1.成员变量
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
private static final long serialVersionUID = 8683452581122892189L;
//默认初始化容量
private static final int DEFAULT_CAPACITY = 10;
//用于空实例的共享空数组实例
private static final Object[] EMPTY_ELEMENTDATA = {};
//默认大希奥的空实例的共享空数组实例
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
//缓冲区》》存储元素的数组
transient Object[] elementData;
//包含的元素个数
private int size;
...
值得注意的是,初始化容量为10,即调用无参构造方法生成的ArrayList对象初始大小是10;
size 表示的是当前arrayList对象包含的有效元素的个数;
2.构造方法
//指定初始化容量的构造方法
public ArrayList(int initialCapacity) {
if (initialCapacity > 0) {
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
this.elementData = EMPTY_ELEMENTDATA;
} else {
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
}
}
//无参构造函数,默认创建一个空集合,size()=0,初始容量jdk1.7之前是10,jdk1.8开始初始化为零在第一次添加元素的时候设为10
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
3.关键方法---add,扩容后为原来的1.5倍
- 确保数组已占用长度+1之后还够存下一个数据
- 计算数组容量,若当前数组已使用长度+1后大于当前数组长度,进行扩容为1.5倍
- 确保位置足够时,添加新元素到size的位置上
4.常见问题
- 什么时候扩容,比如, new ArrayList(10)实例化一个对象,这个过程扩容几次
- 该操作只是实例了一个ArrayList,指定容量为10,没有扩容操作,当添加第十一个元素的时候会进行扩容,扩容后长度为15
- 数组列表之间转换方式
数组》》列表 Arrays.asList(str[]);
列表》》数组 String[] str = list.toArray(new String[list.size()];- 数组转列表后,修改数组的内容,列表受影响吗
列表会受影响,因为列表只是对原有数组进行了一个封装,指向的是同一个内存地址- 坑列表转数组后,列表改动,数组会受影响吗
原数组并不会受影响,因为底层是对原数组的拷贝,根源数组无关系