后续我会陆陆续续更新java源码的一些阅读。大家如果觉得对自己有用就点个关注吧。
文中描述如有问题,欢迎留言指证。
引言
本文中的例子我尽量写的简单,避免一些我平时查资料时一些例子中出现的大量无用代码,产生让人阅读不下去的感觉
ArrayList
描述:其实ArrayList本质就是数组.(外带一句LinkList是链表)
数组的特点:
- 数组存储在内存中是连续的.
- 由于是连续的所以插入和删除效率就会比较慢(相对链表等)因为插入一个数值,后面的元素都要依次往后移,删除的话后面的元素都会依次往前移.
- 随意访问数据很快,因为数组是连续的,知道每一个数据的内存地址,可以直接找到给地址的数据。
链表的特点
- 链表随机访问很慢,因为每次访问一个变量都需要循环,从第一个元素开始比遍历
- 插入和删除很容易,因为链表不涉及到移位,只需要修改节点指针的指向
构造函数
无参构造函数
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
public ArrayList() {this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;}
ArrayList的构造函数默认创建一个空数据,长度为0.
注意:这个时候默认创建的数据长度为0
数据操作方法
add方法
代码第一部分
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
这个方法会在添加第一个元素时默认设置成一个长度为10数组
代码第二部分
进入第一行子方法
private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
代码第三部分
再次进入子方法
这是前面定义的变量 (省的你再去找了)-> private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
private static int calculateCapacity(Object[] elementData, int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
return minCapacity;
}
这个方法就有说道了, if 里面会判断我们数据是不是初始化的那个空数组,如果是我们会返回一个初始化的值
DEFAULT_CAPACITY
这个值是个常量他等于10
好了我们回到代码里,在第二部分中,我们通过第三部分获取到了一个int类型的参数,并将这个参数传入ensureExplicitCapacity()
这个 方法当中,接下来我们来看一看这个方法都写了什么
代码第四部分
//minCapacity这个参数就是第三部份返回值 -> 这里面我们拿第一次添加举例,这面的参数就行是10
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
//这面elementData.length的长度是0,因为最开始他是个空数组
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
这部分没什么说的,我们会接下来开始调用 grow() 方法
private void grow(int minCapacity) {
// 首先获取数组长度,这里我们拿空数组举例
int oldCapacity = elementData.length;
//>>为二进制运输符,右移一位数,转换为十进制其实就是除以2.(如果二进制运算符不太熟,请自行百度),这一步其实就是准备在扩容计算,扩容1.5倍
int newCapacity = oldCapacity + (oldCapacity >> 1);
//如果ArrayList是初始化状态那么newCapacity - minCapacity 就回小于0
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
//这个位置在判断是长度是否超过int最大值,如果
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// 开始将现在的数组复制到一个新的扩容数据中,所以这个位置要注意下(如果在我们循环插入list时而且数量很大,我们应该先给一个合适的长度,来避免list一直在执行扩容操作)
elementData = Arrays.copyOf(elementData, newCapacity);
}
这个就是ArrayList最重要的方法:总结一下
- 在
new ArrayList()
的时候其实我们是声明一个空数组- 在第一次添加元素的时候会自动扩容成10长度数
当然如果你在
new ArrayList(100)
初始化长度,就不会在第一次添加元素时扩容