https://www.itbaima.cn/zh-CN/document/
Introduction
既然数组无法实现这样的高级表结构,那么我就基于数组,对其进行强化,也就是说,我们存放数据还是使用数组,但是我们可以为其编写一些额外的操作来强化为线性表,像这样底层依然采用顺序存储实现的线性表,我们称为顺序表。
定义一个新的类型:
public class ArrayList<E> { // 泛型E,因为表中要存的具体数据类型待定
int capacity = 10; //当前顺序表的容量
int size = 0; //当前已经存放的元素数量
private Object[] array = new Object[capacity]; //底层存放数据的数组
public void add(E element, int index){ //插入方法需要支持在指定下标位置插入
for (int i = size; i > index; i--) //从后往前,一个一个搬运元素
array[i] = array[i - 1];
array[index] = element; //腾出位置之后,直接插入元素放到对应位置上
size++; //插入完成之后,记得将size自增
}
}当插入元素时,需要将插入位置给腾出来,也就是将后面的所有元素向后移,同样的,如果要删除元素,那么也需要将所有的元素向前移动,顺序表是紧凑的,不能出现空位。
只不过这样并不完美,因为我们的插入操作并不是在任何位置都支持插入的,我们允许插入的位置只能是 [0, size] 这个范围内
所以说我们需要在插入之前进行判断:
public void add(E element, int index){
if(index < 0 || index > size) //插入之前先判断插入位置是否合法
throw new IndexOutOfBoundsException("插入位置非法,合法的插入位置为:0 ~ "+size);
for (int i = size; i > index; i--){
array[i] = array[i - 1];
}
array[index] = element;
size++;
}给add方法加入扩容机制
System.arraycopy()
arraycopy
public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length)
参数 类型 说明 srcObject 源数组 srcPosint 源数组的起始位置(索引) destObject 目标数组 destPosint 目标数组的起始位置(索引) lengthint 要复制的元素个数 int[] src = {1, 2, 3, 4, 5}; int[] dest = new int[5]; System.arraycopy(src, 1, dest, 0, 3); // 从src[1]开始,复制3个元素到dest[0] for (int i : dest) { System.out.print(i + " "); }Link to original结果:2 3 4 0 0
if(capacity == size) {
int newCapacity = capacity + (capacity >> 1); //扩容规则就按照原本容量的1.5倍来吧
Object[] newArray = new Object[newCapacity]; //创建一个新的数组来存放更多的元素
System.arraycopy(array, 0, newArray, 0, size); //使用arraycopy快速拷贝原数组内容到新的数组
array = newArray; //更换为新的数组
capacity = newCapacity; //容量变成扩容之后的
}删除元素
public E remove(int index){
if(index < 0 || index > size - 1)
throw new IndexOutOfBoundsException("删除位置非法,合法的插入位置为:0 ~ "+(size - 1));
E e = (E) array[index];
for (int i = index; i < size -; i++)
array[i] = array[i + 1];
size--;
return e;
}