动态数组
动态数组三姐妹:大小、容量、静态数组。
public class DynamicArray {
// 属性:大小、容量、静态数组
private int size = 0;
private int capacity = 8;
private int[] array = new int[capacity];
}
接下来就是熟悉的增删改查环节了。
添加
添加在哪加呢,尾部啦!
public class DynamicArray {
// 属性:大小、容量、静态数组
private int size = 0;
private int capacity = 8;
private int[] array = new int[capacity];
// 添加
public void addLast(int addNum) {
array[size++] = addNum;
}
}
但是我现在不想在尾部添加,我想在哪加就在哪加。OK,满足!
public class DynamicArray {
// 属性:大小、容量、静态数组
private int size = 0;
private int capacity = 8;
private int[] array = new int[capacity];
// 添加
public void addLast(int addNum) {
array[size++] = addNum;
}
public void add(int addNum, int index) {// index---索引
// 边界安全
if (index >= 0 && index < size) {
System.arraycopy(array, index, array,
index + 1, size - index);
}
array[index] = addNum;
size++;
}
}
这里也可以用循环移位来实现。
查找
就直接上代码了。
public class DynamicArray {
// 属性:大小、容量、静态数组
private int size = 0;
private int capacity = 8;
private int[] array = new int[capacity];
// 添加
public void addLast(int addNum) {
array[size++] = addNum;
}
public void add(int addNum, int index) {// index---索引
// 边界安全
if (index >= 0 && index < size) {
System.arraycopy(array, index, array,
index + 1, size - index);
}
array[index] = addNum;
size++;
}
// 查找
public int get(int index) {
if (index >= 0 && index < size) {
return array[index];
}
throw new RuntimeException("角标越界");
}
}
遍历
接下来就是我们要封装遍历操作了。
方式1:普通方式
普通方式就是通过普通的循环遍历。
public class DynamicArray {
// 属性:大小、容量、静态数组
private int size = 0;
private int capacity = 8;
private int[] array = new int[capacity];
// 添加
public void addLast(int addNum) {
array[size++] = addNum;
}
public void add(int addNum, int index) {// index---索引
// 边界安全
if (index >= 0 && index < size) {
System.arraycopy(array, index, array,
index + 1, size - index);
}
array[index] = addNum;
size++;
}
// 查找
public int get(int index) {
if (index >= 0 && index < size) {
return array[index];
}
throw new RuntimeException("角标越界");
}
// 遍历---普通实现
public void froeach() {
for (int i = 0; i < size; i++) {
System.out.println(array[i]);
}
}
}
方式2:函数式接口—Consumer
public class DynamicArray {
// 属性:大小、容量、静态数组
private int size = 0;
private int capacity = 8;
private int[] array = new int[capacity];
// 添加
public void addLast(int addNum) {
array[size++] = addNum;
}
public void add(int addNum, int index) {// index---索引
// 边界安全
if (index >= 0 && index < size) {
System.arraycopy(array, index, array,
index + 1, size - index);
}
array[index] = addNum;
size++;
}
// 查找
public int get(int index) {
if (index >= 0 && index < size) {
return array[index];
}
throw new RuntimeException("角标越界");
}
// 遍历---普通实现
public void froeach() {
for (int i = 0; i < size; i++) {
System.out.println(array[i]);
}
}
// 遍历---函数式接口
public void froeach(Consumer<Integer> consumer) {
for (int i = 0; i < size; i++) {
consumer.accept(array[i]);
}
}
}
测试代码:
@Test
public void test2() {
DynamicArray dynamicArray = new DynamicArray();
dynamicArray.addLast(1);
dynamicArray.addLast(2);
dynamicArray.addLast(3);
dynamicArray.addLast(4);
dynamicArray.addLast(5);
dynamicArray.froeach(element -> System.out.println(element));
}
这里的lambda表达式也可以用方法引用来替代哈~
方式3:迭代器
实现迭代器之前要先实现接口Iterable。
实现迭代器要重写两个方法:hasNext()、Next()。
public class DynamicArray implements Iterable<Integer> {
// 属性:大小、容量、静态数组
private int size = 0;
private int capacity = 8;
private int[] array = new int[capacity];
// 添加
public void addLast(int addNum) {
array[size++] = addNum;
}
public void add(int addNum, int index) {// index---索引
// 边界安全
if (index >= 0 && index < size) {
System.arraycopy(array, index, array,
index + 1, size - index);
}
array[index] = addNum;
size++;
}
// 查找
public int get(int index) {
if (index >= 0 && index < size) {
return array[index];
}
throw new RuntimeException("角标越界");
}
// 遍历---普通实现
public void froeach() {
for (int i = 0; i < size; i++) {
System.out.println(array[i]);
}
}
// 遍历---函数式接口
public void froeach(Consumer<Integer> consumer) {
for (int i = 0; i < size; i++) {
consumer.accept(array[i]);
}
}
// 遍历---迭代器
public Iterator<Integer> iterator() {
// 匿名实现类的匿名对象
return new Iterator<Integer>() {
int i = 0;
@Override
public boolean hasNext() {
return i < size;
}
@Override
public Integer next() {
return array[i++];
}
};
}
}
方式4:流
public class DynamicArray implements Iterable<Integer> {
// 属性:大小、容量、静态数组
private int size = 0;
private int capacity = 8;
private int[] array = new int[capacity];
// 添加
public void addLast(int addNum) {
array[size++] = addNum;
}
public void add(int addNum, int index) {// index---索引
// 边界安全
if (index >= 0 && index < size) {
System.arraycopy(array, index, array,
index + 1, size - index);
}
array[index] = addNum;
size++;
}
// 查找
public int get(int index) {
if (index >= 0 && index < size) {
return array[index];
}
throw new RuntimeException("角标越界");
}
// 遍历---普通实现
public void froeach() {
for (int i = 0; i < size; i++) {
System.out.println(array[i]);
}
}
// 遍历---函数式接口
public void froeach(Consumer<Integer> consumer) {
for (int i = 0; i < size; i++) {
consumer.accept(array[i]);
}
}
// 遍历---迭代器
public Iterator<Integer> iterator() {
// 匿名实现类的匿名对象
return new Iterator<Integer>() {
int i = 0;
@Override
public boolean hasNext() {
return i < size;
}
@Override
public Integer next() {
return array[i++];
}
};
}
// 遍历---流实现
public IntStream stream() {
return IntStream.of(Arrays.copyOfRange(array, 0, size));// [0,size)
}
}
遍历方式大概是这几种方式。
接下来就是删除操作。
删除
public class DynamicArray implements Iterable<Integer> {
// 属性:大小、容量、静态数组
private int size = 0;
private int capacity = 8;
private int[] array = new int[capacity];
// 添加
public void addLast(int addNum) {
array[size++] = addNum;
}
public void add(int addNum, int index) {// index---索引
// 边界安全
if (index >= 0 && index < size) {
System.arraycopy(array, index, array,
index + 1, size - index);
}
array[index] = addNum;
size++;
}
// 查找
public int get(int index) {
if (index >= 0 && index < size) {
return array[index];
}
throw new RuntimeException("角标越界");
}
// 遍历---普通实现
public void froeach() {
for (int i = 0; i < size; i++) {
System.out.println(array[i]);
}
}
// 遍历---函数式接口
public void froeach(Consumer<Integer> consumer) {
for (int i = 0; i < size; i++) {
consumer.accept(array[i]);
}
}
// 遍历---迭代器
public Iterator<Integer> iterator() {
// 匿名实现类的匿名对象
return new Iterator<Integer>() {
int i = 0;
@Override
public boolean hasNext() {
return i < size;
}
@Override
public Integer next() {
return array[i++];
}
};
}
// 遍历---流实现
public IntStream stream() {
return IntStream.of(Arrays.copyOfRange(array, 0, size));// [0,size)
}
// 删除
public int remove(int index) {// 返回被删除的元素
int removedNun = array[index];
System.arraycopy(array, index + 1,
array, index, size - index - 1);
size--;
return removedNun;
}
}
基本操作已经结束了,现在我们再思考之前的添加操作。
既然是动态数组,扩容是必然的,所以我们的添加操作要考虑扩容。
并且可以对addLast方法进行发代码层面的优化,它可以调用add方法。
对于一开始我们就给我们的静态数组分配了空间,如果长时间不用,在内存中会长时间占据空间,因此可以参考设计模式中的懒汉式单例。
public class DynamicArray implements Iterable<Integer> {
// 属性:大小、容量、静态数组
private int size = 0;
private int capacity = 8;
private int[] array = {};// 类似懒汉式
// 添加
public void addLast(int addNum) {
add(addNum, size);
}
public void add(int addNum, int index) {
checkAndGrow();
// 添加逻辑
if (index >= 0 && index < size) {
// 向后挪动, 空出待插入位置
System.arraycopy(array, index,
array, index + 1, size - index);
}
array[index] = addNum;
size++;
}
private void checkAndGrow() {
// 容量检查
if (size == 0) {
array = new int[capacity];
} else if (size == capacity) {
// 进行扩容, 扩为原来的1.5倍
capacity += capacity >> 1;
int[] newArray = new int[capacity];
System.arraycopy(array, 0,
newArray, 0, size);
array = newArray;
}
}
// 查找
public int get(int index) {
if (index >= 0 && index < size) {
return array[index];
}
throw new RuntimeException("角标越界");
}
// 遍历---普通实现
public void froeach() {
for (int i = 0; i < size; i++) {
System.out.println(array[i]);
}
}
// 遍历---函数式接口
public void froeach(Consumer<Integer> consumer) {
for (int i = 0; i < size; i++) {
consumer.accept(array[i]);
}
}
// 遍历---迭代器
public Iterator<Integer> iterator() {
// 匿名实现类的匿名对象
return new Iterator<Integer>() {
int i = 0;
@Override
public boolean hasNext() {
return i < size;
}
@Override
public Integer next() {
return array[i++];
}
};
}
// 遍历---流实现
public IntStream stream() {
return IntStream.of(Arrays.copyOfRange(array, 0, size));// [0,size)
}
// 删除
public int remove(int index) {// 返回被删除的元素
int removedNun = array[index];
System.arraycopy(array, index + 1,
array, index, size - index - 1);
size--;
return removedNun;
}
}