动态数组是什么
之前写过一篇数组和静态数组的介绍:数组的定义和特点,静态数组CURD的实现
我们在静态数组的基础上,增加一些比较方便的功能,比如自动扩容,获取数组长度等,这样的数组叫动态数组
动态数组的本质仍旧是静态数组,静态数组的特点它都有,只不过通过一些标记的变量新增了一些方法,方便我们进行CURD而已
相比于静态数组新增的功能
- 自动缩扩容
- addLast,add
- deleteLast,delete
- get,set(修改)
- size
- isEmpty
初始化动态数组
- 使用泛型可以创建任意类型的数组
- data即为真实的数组存放空间所在
- size是数组中存放数据的数量,初始为1
- INIT_CAPACITY 是默认的数组长度
- 提供了有参和无参构造
public class MyDynamicArray<E> {
private E[] data;// 数据
private Integer size;// 数据容量
private static final Integer INIT_CAPACITY = 10;// 初始容量
public MyDynamicArray() {
this(INIT_CAPACITY);
}
public MyDynamicArray(int initCapacity) {
this.data = (E[]) new Object[initCapacity];
this.size = 0;
}
public static void main(String[] args) {
MyDynamicArray<Integer> dynamicArray = new MyDynamicArray<>();
MyDynamicArray<String> dynamicArray2 = new MyDynamicArray<>(20);
}
}
扩容/缩容
// 扩容/缩容
public void resize(int newSize) {
E[] newData = (E[]) new Object[newSize];
int minSize = Math.min(this.size, newSize);
for (int i = 0; i < minSize; i++) {
newData[i] = this.data[i];
}
data = newData;
}
add,addLast实现
// 尾部增
public void addLast(E e) {
int l = this.data.length;
if (size == l) {
resize(2 * l);
}
// 在尾部插入元素
data[size] = e;
size++;
}
public void add(int index, E e) {
// 判断index是否合法
if (!isIndexValid(index)) {
throw new IndexOutOfBoundsException();
}
int l = this.data.length;
if (size == l) {
resize(2 * l);
}
for (int i = size-1; i >= index; i--) {
data[i+1] = data[i];
}
data[index] = e;
size++;
}
public boolean isIndexValid(int index) {
// 数组要保证元素连续,不能让两个元素之间有空位
return index >= 0 && index < this.size;
}
delete,deleteLast实现
// 删除尾部元素
public E deleteLast() {
if (size == 0) {
throw new NoSuchElementException();
}
int l = data.length;
// 可以缩容,节约空间
if (size == l/ 4) {
resize(l/ 2);
}
E deletedVal = data[size - 1];
// 删除最后一个元素
// 必须给最后一个元素置为 null,否则会内存泄漏
data[size - 1] = null;
size--;
return deletedVal;
}
// 删除中间元素
public E delete(int index) {
// 判断index是否合法
if (!isIndexValid(index)) {
throw new IndexOutOfBoundsException();
}
int l = this.data.length;
// 缩容节约空间
if (size == l / 4) {
resize(l / 2);
}
E deletedVal = data[index];
for (int j = index + 1; j < size; j++) {
data[j - 1] = data[j];
}
data[size - 1] = null;
size--;
return deletedVal;
}
get和set
// 查询
public E get(int index) {
// 判断index是否合法
if (!isIndexValid(index)) {
throw new IndexOutOfBoundsException();
}
return data[index];
}
// 赋值
public void set(int index, E newData) {
// 判断index是否合法
if (!isIndexValid(index)) {
throw new IndexOutOfBoundsException();
}
data[index] = newData;
}
size
public Integer size() {
return size;
}
isEmpty
public boolean isEmpty() {
return size == 0;
}
测试
import java.util.Arrays;
import java.util.NoSuchElementException;
public class MyDynamicArray<E> {
private E[] data;// 数据
private Integer size;// 数据容量
private static final Integer INIT_CAPACITY = 5;// 初始容量
public MyDynamicArray() {
this(INIT_CAPACITY);
}
public MyDynamicArray(int initCapacity) {
this.data = (E[]) new Object[initCapacity];
this.size = 0;
System.out.print("===初始状态:");
display();
}
// 扩容/缩容
public void resize(int newSize) {
E[] newData = (E[]) new Object[newSize];
int minSize = Math.min(this.size, newSize);
for (int i = 0; i < minSize; i++) {
newData[i] = this.data[i];
}
data = newData;
System.out.println("===旧size:" + this.size + ",新size:" + newSize);
System.out.print("===扩容/缩容之后:");
display();
}
// 尾部增
public void addLast(E e) {
int l = this.data.length;
if (size == l) {
resize(2 * l);
}
// 在尾部插入元素
data[size] = e;
size++;
System.out.print("===尾插入后:");
display();
}
public void add(int index, E e) {
// 判断index是否合法
if (!isIndexValid(index)) {
throw new IndexOutOfBoundsException();
}
int l = this.data.length;
if (size == l) {
resize(2 * l);
}
for (int i = size - 1; i >= index; i--) {
data[i + 1] = data[i];
}
data[index] = e;
size++;
System.out.print("===中间插入后:");
display();
}
// 删除尾部元素
public E deleteLast() {
if (size == 0) {
throw new NoSuchElementException();
}
int l = data.length;
// 缩容节约空间
if (size == l / 4) {
resize(l / 2);
}
E deletedVal = data[size - 1];
// 删除最后一个元素
// 必须给最后一个元素置为 null,否则会内存泄漏
data[size - 1] = null;
size--;
System.out.print("===尾删除后:");
display();
return deletedVal;
}
// 删除中间元素
public E delete(int index) {
// 判断index是否合法
if (!isIndexValid(index)) {
throw new IndexOutOfBoundsException();
}
int l = this.data.length;
// 缩容节约空间
if (size == l / 4) {
resize(l / 2);
}
E deletedVal = data[index];
for (int j = index + 1; j < size; j++) {
data[j - 1] = data[j];
}
data[size - 1] = null;
size--;
System.out.print("===中间删除后:");
display();
return deletedVal;
}
// 查询
public E get(int index) {
// 判断index是否合法
if (!isIndexValid(index)) {
throw new IndexOutOfBoundsException();
}
return data[index];
}
// 赋值
public void set(int index, E newData) {
// 判断index是否合法
if (!isIndexValid(index)) {
throw new IndexOutOfBoundsException();
}
data[index] = newData;
System.out.print("===修改后:");
display();
}
public Integer size() {
return size;
}
public boolean isEmpty() {
return size == 0;
}
public boolean isIndexValid(int index) {
// 数组要保证元素连续,不能让两个元素之间有空位
return index >= 0 && index < this.size;
}
public void display() {
System.out.println(Arrays.toString(data));
}
public static void main(String[] args) {
MyDynamicArray<Integer> dynamicArray = new MyDynamicArray<>();
dynamicArray.addLast(1);
dynamicArray.addLast(2);
dynamicArray.addLast(3);
dynamicArray.addLast(4);
dynamicArray.addLast(5);
dynamicArray.addLast(6);
dynamicArray.add(2, 100);
dynamicArray.deleteLast();
dynamicArray.delete(3);
System.out.println("===get方法结果:" + dynamicArray.get(3));
dynamicArray.set(2,666);
dynamicArray.deleteLast();
dynamicArray.deleteLast();
dynamicArray.deleteLast();
dynamicArray.deleteLast();
}
}
运行结果
我们可以很清楚的看到扩容和缩容,删除和新增等操作的实现