前两篇本质上还是静态数组,静态数组容量是有限的。但有时我们无法预估将要使用的数组有多大,太大太小都不好。解决方案:数组容量是可伸缩的。本篇就是实现可伸缩的动态数组
实现原理:
数组增加/缩减:1 当发现不够用或者过多时,开辟一个newData,容量是之前的data的两倍/一半
2 将data原样复制到newData中
3 使data指向newData
resize(newCapacity) {
1 newData
2 将data复制到newData
3 data指向newData
}
根据resize()传入的参数值,可以变成两倍或者0.5倍等等,所以可以进行扩容或者缩减容量
更改add方法,添加扩容功能
//在第index个位置添加一个新元素
public void add(int index, E e) {
if (index < 0 || index > size) {
//index>size 代表不是紧密地在最后添加,会有跳过的地方
throw new IllegalArgumentException("AddElement failed. Require index < 0 || index > size.");//先抛个异常,以后再处理
}
if (size == data.length) {
resize(2 * data.length);
}
//index之后的元素依次向后挪动,然后将e放到poz处,size增加1
//要被处理i的开始位置是index结束位置是size-1
for (int i = size - 1; i >=index; i --) {
data[i + 1] = data[i];
}
data[index] = e;
size ++;
}
//实现扩容功能
public void resize(int newCapacity){
E[] newData = (E[])new Object[newCapacity];
for (int i = 0; i < size; i ++){
newData[i] = data[i];
}
data = newData;
}
更改remove方法,添加缩减容量功能
//删除索引为index的某个元素,并且返回该元素的值
//删除索引为index的某个元素,并且返回该元素的值
public E remove (int index) {
E ret = data[index];
if (index < 0 || index > size) {
//index>size 代表不是紧密地在最后添加,会有跳过的地方
throw new IllegalArgumentException("AddElement failed. Require index < 0 || index > size.");//先抛个异常,以后再处理
}
//index之后的元素依次向前挪动,size减1
//要被处理i的开始位置是size-1结束位置是index
for (int i = index; i < size -1 ; i ++) {
data[i] = data[i + 1];
}
size --;
data[size] = null;
if(size == data.length / 2){
//复用resize 可以变小也可以变大
resize(data.length / 2);
}
return ret;
}