当你停下来休息的时候,不要忘记,别人还在奔跑~
对上篇进行一个补充。。
1.ArrayList扩容Demo
getCapacity()方法通过反射获取ArrayList的容量。
public static Integer getCapacity(ArrayList list) {
Integer lenth = null;
Class c = list.getClass();
Field field;
try {
field = c.getDeclaredField("elementData");
field.setAccessible(true);
Object[] o = new Object[0];
try {
o = (Object[]) field.get(list);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
lenth = o.length;
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
return lenth;
}
第一次初始化ArrayList
public static void main(String[] args) {
ArrayList<String> arrayList = new ArrayList<>();
Integer capacity = getCapacity(arrayList);
System.out.println("容量:"+capacity);
System.out.println("大小:" +arrayList.size());
}
添加第一个元素的时候
public static void main(String[] args) {
ArrayList<String> arrayList2 = new ArrayList<>();
for (int i = 1; i <= 1; i++) {
arrayList2.add("value" + i);
}
Integer capacity = getCapacity(arrayList2);
System.out.println("容量:" + capacity);
System.out.println("大小:" + arrayList2.size());
}
将i改为9,添加第9个元素
将i改为11,添加第11个元素
将i改为16,添加第16个元素
将i改为23,添加第23个元素
综上:
当数组中添加第一个元素时,数组容量扩为10(默认值DEFAULT_CAPACITY=10)。直到Size+1大于数组容量时,就会去扩容,ArrayList 每次扩容之后容量确实变为原来的 1.5 倍左右(oldCapacity为偶数就是1.5倍,否则是1.5倍左右)! 奇偶不同,比如 :10+10/2 = 15, 15+15/2=22。如果是奇数的话会丢掉小数。
2.System.arraycopy() 和 Arrays.copyOf()方法
阅读源码的话,我们就会发现 ArrayList 中大量调用了这两个方法。比如:我们上面讲的扩容操作以及add(int index, E element)、toArray() 等方法中都用到了该方法!
/**
* 在此列表中的指定位置插入指定的元素。
*先调用 rangeCheckForAdd 对index进行界限检查;然后调用 ensureCapacityInternal 方法保证capacity足够大;
*再将从index开始之后的所有成员后移一个位置;将element插入index位置;最后size加1。
*/
public void add(int index, E element) {
rangeCheckForAdd(index);
ensureCapacityInternal(size + 1); // Increments modCount!!
//arraycopy()方法实现数组自己复制自己
//elementData:源数组;index:源数组中的起始位置;elementData:目标数组;index + 1:目标数组中的起始位置; size - index:要复制的数组元素的数量;
System.arraycopy(elementData, index, elementData, index + 1, size - index);
elementData[index] = element;
size++;
}
/**
以正确的顺序返回一个包含此列表中所有元素的数组(从第一个到最后一个元素); 返回的数组的运行时类型是指定数组的运行时类型。
*/
public Object[] toArray() {
//elementData:要复制的数组;size:要复制的长度
return Arrays.copyOf(elementData, size);
}
联系:
看两者源代码可以发现 copyOf() 内部实际调用了 System.arraycopy() 方法区别:
arraycopy() 需要目标数组,将原数组拷贝到你自己定义的数组里或者原数组,而且可以选择拷贝的起点和长度以及放入新数组中的位置 copyOf() 是系统自动在内部新建一个数组,并返回该数组。
3.基本常识:
java 中的 length 属性是针对数组说的,比如说你声明了一个数组,想知道这个数组的长度则用到了 length 这个属性.
java 中的 length() 方法是针对字符串说的,如果想看这个字符串的长度则用到 length() 这个方法.
java 中的 size() 方法是针对泛型集合说的,如果想看这个泛型有多少个元素,就调用此方法来查看!