数组
- 基础
- 1.1 什么是数组
- 1.2 数组特点
- 无法动态修改容量
- 内存中顺序存储
- 2. 基本操作
- 2.1 结构
- 2.2 添加元素 - add(E element)、add(int index, E element)
- 代码实现
- 2.3 删除元素 - remove(int index)、清空数组 - clear()
- 代码实现
- 2.4 扩容 - ensureCapacity(int capacity)
- 3. 代码
基础
1.1 什么是数组
数组是一种顺序存储的线性表,所有元素的内存地址是连续的。
1.2 数组特点
无法动态修改容量
内存中顺序存储
2. 基本操作
2.1 结构
2.2 添加元素 - add(E element)、add(int index, E element)
add(E element)
:默认往数组最后添加元素。
add(int index, E element)
:在 index 位置插入一个元素
比如在index=2的位置插入元素,从后往前开始将 index = 2 以后的元素依次后移,然后赋值:
如果从前往后开始移动元素,会造成如下错误的后果:
代码实现
/**
* 队尾插入元素
* @param e 插入的元素
*/
public void add(E e) {
add(size, e);
}
/**
* 指定插入元素
* @param index 插入的位置
* @param e 插入的元素
*/
public void add(int index, E e) {
// 检查下标
rangeCheckForAdd(index);
// 确保容量够大,容量不足的话,1.5倍扩容
ensureCapacity(size + 1);
// 0 1 2 3 4 5 6 7 8 9 (index)
// 1 2 3 4 5 6 x x x x (原数组)
// 在index=2处,插入9,元素全部后移
// 1 2 9 3 4 5 6 x x x (add后数组)
// 先从后往前开始, 将每个元素往后移一位, 然后再赋值
// size-1(最后一个元素) ---> index(index位置也要移走)
for (int i = size - 1; i >= index; i--) {
elementData[i + 1] = elementData[i];
}
elementData[index] = e;
size++;
}
2.3 删除元素 - remove(int index)、清空数组 - clear()
例如,删除 index = 3 的数组元素,应当从前往后开始移动,用后面的元素覆盖前面的元素。
代码实现
//清除所有元素 - clear()
public void clear() {
// 使用泛型数组后要注意内存管理(将元素置null)
for (int i = 0; i < size; i++) {
elements[i] = null;
}
size = 0;
}
/**
* 清除指定位置元素
* @param index 删除的元素位置
* @return
*/
public E remove(int index) {
//检查下标
rangeCheckForAdd(index);
//要被删除的元素,用于return
E old = (E) elementData[index];
// 0 1 2 3 4 5 (index)
// 1 2 3 4 5 6 (原数组)
// 删除index为2的元素,元素前移
// 1 2 4 5 6 (remove后的数组)
// 从前往后开始移, 用后面的元素覆盖前面的元素
// 1. index(第一个元素被覆盖的元素) ---> size-(倒数第二个元素是最后一个被移除的元素)
for (int i = index; i <= size - 1; i++) {
elementData[i] = elementData[i + 1];
}
// 2. 此时,最后一个元素已经被放到倒数第二个元素的位置了,这时候,最后一个元素置为null就可以
elementData[size - 1] = null;
size--;
return old;
}
2.4 扩容 - ensureCapacity(int capacity)
/*
* 扩容操作
*/
private void ensureCapacity(int capacity) {
int oldCapacity = elementData.length;
if (oldCapacity >= capacity) {
return;
}
int newCapacity = oldCapacity + (oldCapacity >> 1); // 1.5
Object[] newElementData = new Object[newCapacity];
// 新容量为旧容量的1.5倍
System.arraycopy(elementData, 0, newElementData, 0, elementData.length);
System.out.println("size=" + oldCapacity + ", 扩容到了" + newCapacity);
//底层
//for (int i = 0; i < size; i++) {
// newElementData[i] = elementData[i];
//}
//elements = newElements;
}
3. 代码
public class ArrayList<E> {
private Object[] elementData; //元素存放位置
public int size; //元素数量
private static final int DEFAULT_CAPACITY = 10; //初始容量
public ArrayList(int size) {
size = (size < DEFAULT_CAPACITY) ? DEFAULT_CAPACITY : size;
elementData = new Object[size];
}
public ArrayList() {
this(DEFAULT_CAPACITY);
}
//读取元素
public E get(int index) {
return (E) elementData[index];
}
/**
* 队尾插入元素
*
* @param e 插入的元素
*/
public void add(E e) {
add(size, e);
}
/**
* 指定插入元素
*
* @param index 插入的位置
* @param e 插入的元素
*/
public void add(int index, E e) {
// 检查下标
rangeCheckForAdd(index);
// 确保容量够大,容量不足的话,1.5倍扩容
ensureCapacity(size + 1);
// 0 1 2 3 4 5 6 7 8 9 (index)
// 1 2 3 4 5 6 x x x x (原数组)
// 在index=2处,插入9,元素全部后移
// 1 2 9 3 4 5 6 x x x (add后数组)
// 先从后往前开始, 将每个元素往后移一位, 然后再赋值
// size-1(最后一个元素) ---> index(index位置也要移走)
for (int i = size - 1; i >= index; i--) {
elementData[i + 1] = elementData[i];
}
elementData[index] = e;
size++;
}
//清除所有元素 - clear()
public void clear() {
elementData = null;
size = 0;
}
/**
* 清除指定位置元素
*
* @param index 删除的元素位置
* @return
*/
public E remove(int index) {
//检查下标
rangeCheckForAdd(index);
//要被删除的元素,用于return
E old = (E) elementData[index];
// 0 1 2 3 4 5 (index)
// 1 2 3 4 5 6 (原数组)
// 删除index为2的元素,元素前移
// 1 2 4 5 6 (remove后的数组)
// 从前往后开始移, 用后面的元素覆盖前面的元素
// 1. index(第一个元素被覆盖的元素) ---> size-(倒数第二个元素是最后一个被移除的元素)
for (int i = index; i <= size - 1; i++) {
elementData[i] = elementData[i + 1];
}
// 2. 此时,最后一个元素已经被放到倒数第二个元素的位置了,这时候,最后一个元素置为null就可以
elementData[size - 1] = null;
size--;
return old;
}
/*
* 扩容操作
*/
private void ensureCapacity(int capacity) {
int oldCapacity = elementData.length;
if (oldCapacity >= capacity) {
return;
}
int newCapacity = oldCapacity + (oldCapacity >> 1); // 1.5
Object[] newElementData = new Object[newCapacity];
// 新容量为旧容量的1.5倍
System.arraycopy(elementData, 0, newElementData, 0, elementData.length);
System.out.println("size=" + oldCapacity + ", 扩容到了" + newCapacity);
elementData = newElementData;
//底层
//for (int i = 0; i < size; i++) {
// newElementData[i] = elementData[i];
//}
//elements = newElements;
}
// 检查add()的下标越界(可以在size位置添加)
private void rangeCheckForAdd(int index) {
if (index < 0 || index > size) {
throw new IndexOutOfBoundsException("Index:" + index + ", Size:" + size);
}
}
}
视频链接找不到了,
参考博客:https://blog.csdn.net/weixin_43734095/article/details/104598981