300字范文,内容丰富有趣,生活中的好帮手!
300字范文 > 回味集合(三)ArrayList的add方法

回味集合(三)ArrayList的add方法

时间:2020-07-03 06:48:04

相关推荐

回味集合(三)ArrayList的add方法

啥也不说了,直接撸源码:

public class ArrayList<E> extends AbstractList<E>implements List<E>, RandomAccess, Cloneable, java.io.Serializable

从上述代码中我们可以看出继承了AbstractListList接口,实现了RandomAccessCloneable两个接口,其中RandomAccess接口中没有任何方法,他只是一个标识,说明实现该接口的类是一个可以随机访问的类方便查询,Cloneable是标记型的接口,它们内部都没有方法和属性,实现Cloneable来表示该对象能被克隆,能使用Object.clone()方法。如果没有实现Cloneable的类对象调用clone()就会抛出CloneNotSupportedException

今天我们重点看的是ArrayList中的add方法:

1.先说几个关键的几个全局变量:

//用于定于初始的大小private static final int DEFAULT_CAPACITY = 10;//默认初始容量。private static final Object[] EMPTY_ELEMENTDATA = {};//用于空实例的共享空数组实例private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};//操作数组transient Object[] elementData;//ArrayList的大小(它包含的元素数)private int size;

2.构造器

//给定初始大小public ArrayList(int initialCapacity) {//判断initialCapacity是否大于0if (initialCapacity > 0) {//如果大于0,则将initialCapacity作为ArrayList的初始大小this.elementData = new Object[initialCapacity];} else if (initialCapacity == 0) {//如果等于0则将赋值一个空数组作为ArrayList的初始容量this.elementData = EMPTY_ELEMENTDATA;} else {throw new IllegalArgumentException("Illegal Capacity: "+initialCapacity);}}

//在使用无参构造时,默认给ArrayList初始容量为0public ArrayList() {this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;}

从上面的两个构造器可以看出ArrayList底层实现是数组,并且在不给定初始大小时,默认大小为0。

3.添加方法add()

public boolean add(E e) {//size记录的是ArrayList的大小(它包含的元素数),并加让当前seiz+1ensureCapacityInternal(size + 1); //对组大小进行判断或扩容完成后,将新的元素添加大最后一个位置elementData[size++] = e;//返回true,表示添加成功return true;}

ArrayList在调用add方法添加元素时,首先会调用ensureCapacityInternal(size + 1)方法,对数组大小进行判断及扩容如下分析:

//minCapacity为实际元素个+1的大小private void ensureCapacityInternal(int minCapacity) {// elementData为容纳元素的数组//minCapacity为实际元素个+1的大小ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));}

发现ensureCapacityInternal方法内部又调用了ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));方法,

ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));中他先调用的是calculateCapacity(elementData, minCapacity)方法:

// elementData为容纳元素的数组//minCapacity为实际元素个+1的大小private static int calculateCapacity(Object[] elementData, int minCapacity) {//判断当数组是否为空数组,如果 elementData为空说明刚初始化的新实例对象, //准备添加一个元素if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {//给初始化新实例分配容量:10return Math.max(DEFAULT_CAPACITY, minCapacity);}//如果elementData不为空说明刚此实例对象不是新初始化的,已经有元素了//返回数据的实际大小 return minCapacity;}

//通过之前的判断得到数据的大小minCapacityprivate void ensureExplicitCapacity(int minCapacity) {modCount++;//用数组中实际元素个数-数组长度//如果结果>0,说明元素个数已经超过的数组的大小,不能继续添加元素,需要进行数组扩容//如果结果<0,说明元素个数还没有超过的数组的大小,还可以继续添加元素if (minCapacity - elementData.length > 0)//扩容:minCapacity为实际元素个数+1grow(minCapacity);}

private void grow(int minCapacity) {//得到数组的大小int oldCapacity = elementData.length;//通过位运算得到新数组的大小:旧数组大小+旧数组的大小的一半int newCapacity = oldCapacity + (oldCapacity >> 1);//判断新数组大小是否大于当前数组元素个数+1的大小if (newCapacity - minCapacity < 0)//如果newCapacity - minCapacity < 0说明新长度不能满足//则将minCapacity当做新的数组长度newCapacity = minCapacity; if (newCapacity - MAX_ARRAY_SIZE > 0)newCapacity = hugeCapacity(minCapacity);//对数组进行扩容将elementData大小扩容为新的长度,并将老数组中大元素移动到新的数组中elementData = Arrays.copyOf(elementData, newCapacity);}

扩展:

Arrays的copyOf()方法传回的数组是新的数组对象,改变传回数组中的元素值,不会影响原来的数组。

copyOf()的第二个自变量指定要建立的新数组长度,如果新数组的长度超过原数组的长度,则保留数组默认值,例如:

import java.util.Arrays;public class ArrayDemo {public static void main(String[] args) {int[] arr1 = {1, 2, 3, 4, 5}; int[] arr2 = Arrays.copyOf(arr1, 5);int[] arr3 = Arrays.copyOf(arr1, 10);for(int i = 0; i < arr2.length; i++) System.out.print(arr2[i] + " "); System.out.println();for(int i = 0; i < arr3.length; i++) System.out.print(arr3[i] + " ");}}

结果:

1 2 3 4 5 1 2 3 4 5 0 0 0 0 0

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。