一、动态数组产生的原因
在许多编程语言中数组是无法动态修改容量,所以需要数组的长度能够进行动态的变化, 在java JDK内置了动态数组类:java.util.ArrayList
二、动态数组的主要接口实现
1、构造方法
如果创建数组的空间小于默认空间,则会以默认空间创建数组
public class ArrayList<E> {
private int size;
private E[] elements;
private static final int CAPACITY_DEFAULT = 10;
public ArrayList(int capacity) {
capacity = (capacity < CAPACITY_DEFAULT) ? CAPACITY_DEFAULT : capacity;
elements = (E[]) new Object[capacity];
}
public ArrayList() {
this(CAPACITY_DEFAULT);
}
}
2、添加元素
添加元素可以分为两种情况:
- 在数组末尾添加元素即插入到数组的尾部size处
public void add(E element) {
add(size, element);
}
- 在数组中间插入元素
public void add(int index, E element) {
if (index < 0 || index > size) {
throw new IndexOutOfBoundsException("index:" + index + ", Size:" + size);
}
// 检测是否需要扩容
ensureCapacity(size + 1);
for (int i = size; i > index; i--) {
elements[i] = elements[i - 1];
}
elements[index] = element;
size++;
}
2.1、数组动态扩容
实现策略:
- 在加入元素之前首先进行判断是否需要扩容
- 如果需要创建一个新的数组,新数组的大小官方设置是原数组的1.5倍
- 将原数组中的元素存到新的数组中
private void ensureCapacity(int capacity) {
// 获得当前数组的容量
int oldCapacity = elements.length;
if (oldCapacity > capacity) return;
// 扩容的大小使原来的1.5倍,位运算符的运算较快
int newCapacity = oldCapacity + (oldCapacity >> 1);
E[] newElements = (E[]) new Object[newCapacity];
for (int i = 0; i < size; i++) {
newElements[i] = elements[i];
}
// 引用新数组
elements = newElements;
}
3、删除元素
指定元素的下标,将后面的元素逐个向前移,覆盖掉前面的元素
public E remove(int index) {
if (index < 0 || index >= size) {
throw new IndexOutOfBoundsException("index:" + index + ", Size:" + size);
}
E element = elements[index];
for (int i = index; i < size; i++) {
elements[i] = elements[i + 1];
}
elements[--size] = null;
// 是否需要缩容
trim();
return element;
}
3.1、动态缩容
为了避免内存的浪费,当数组中的元素小于一定数量后进行缩容
private void trim(){
int capacity = elements.length;
if (size >= capacity >> 1 || capacity < CAPACITY_DEFAULT) return;
// 新的容量为原来容量的一半
int newCapacity = capacity >> 1;
E[] newElements = (E[]) new Object[newCapacity];
for (int i = 0; i < size; i++){
newElements[i] = elements[i];
}
elements = newElements;
}
三、动态数组的复杂度
增删元素的最好时间复杂度是O(1),最坏是O(n),平均时间复杂度是O(n)
改查的时间辅助度是O(1)级别,因为是通过数组的索引来实现