java实现动态数组
概述
实现
package com.lovehena.datastructure;
import lombok.extern.slf4j.Slf4j;
/*
* java实现一个动态数组
* 实际上,java.util.ArrayList这个类就是一个动态数组的类
* 和静态数组最大的不同就是,java.util.ArrayList中的元素个数是可以变化的。
*
* 一个动态数组中至少要有3个属性:
* 1.size 动态数组中已有元素的个数
* 2.capacity 动态数组中最大的元素个数
* 3.arr 虽然我们要实现的是一个动态数组,但还是需要一个静态数组用于存储元素,当静态数组无法容纳更多元素时动态扩容,于是,动态数组就实现了
*
* 先实现以下3个方法:
* 1.add(int index,int element) 往数组中指定索引处添加元素
* 2.addLast(int element) 将欲添加的元素添加到数组最后面
* 3.print() 数组的遍历
* */
@Slf4j
public class MyArrayList {
private int size = 0; // 动态数组中已手动添加的元素的个数 初始时一个手动添加的元素也没有
private int capacity = 10; // 动态数组中最大的元素个数 默认为10 java.util.ArrayList的默认初始容量也是10
// 初始化一个静态数组 用于存储元素
// 数组中的元素类型默认都是整数 如果需要存储其他类型 可以利用泛型机制实现
// 实际上 int[] arr=new int[capacity] 这行代码执行完时 arr中已经有10个元素了 并且每个元素的值都是0
private int[] arr = new int[capacity];
/**
* 往数组中指定索引处添加元素
* 思路:
* 已有数组
* 元素 1 2 3 4 5
* 索引 0 1 2 3 4
*
* 现在要往索引为2的位置添加一个元素100,则 3 4 5这3( 3 = size - index )个元素都要往后移动1位,将索引为2的位置空出来,再将目标元素插入在索引2处即可
* 保证占用的内存空间是连续的
* @param index 目标索引
* @param element 目标元素
*/
public void add(int index, int element) {
if (index < 0 || index >= capacity) { // index最大值为capacity-1 最小值为0
log.error("索引:{} 不正确", index);
return;
}
// 利用System.arraycopy完成数组中元素的移动 api不熟悉的话可以点进源码阅读下注释
// destPos的最大值为index(而不是index+1 java api设计中大多都是含头不含尾)
System.arraycopy(arr, index, arr, index + 1, size - index);
arr[index] = element;
size++; // 已手动添加的元素的个数+1 这个size其实类似于实现链表时的头节点(头指针)
}
/*
* 1 2 3 4 5 6 7 8 9 10
* 0 1 2 3 4 5 6 7 8 9
*
* */
/**
* 将欲添加的元素添加到数组最后面
* 思路:
* 已有数组
* 元素 1 2 3 4 5
* 索引 0 1 2 3 4
*
* 现在要将6插入到数组的最后面,即插入到索引为5( size = 5)的位置,所以调用add传入index为size即可
*
* 实际上 很多代码的书写都是先总结规律 再写出来的
* @param element 欲添加的元素
*/
public void addLast(int element){
// 直接调用add方法即可
add(size,element);
}
/**
* 数组遍历
*/
public void print(){
/*
为什么不是这么写?
for (int i = 0; i < arr.length; i++) {
}
因为 数组中真正添加了几个元素是由size表示的 我们遍历时需要的是我们手动添加的元素
而不是数组初始化时默认初始化的为0的元素
*/
StringBuilder sb = new StringBuilder();
for (int i = 0; i < size; i++) {
sb.append(arr[i]).append(" ");
}
log.info("遍历数组 数组为:{}\n",sb.toString());
}
//todo 扩展:数组遍历的逻辑由调用者自定义,而不是直接写死在print()中,如何实现?
//todo 扩展:以上的代码和动态数组(动态扩容)还没关系,感兴趣的朋友可以自己先实现下。
}
测试用例
@Slf4j
public class TestMyArrayList {
public static void main(String[] args) {
MyArrayList list = new MyArrayList();
list.add(0,1);
list.add(1,2);
list.add(2,3);
list.print();
list.addLast(4);
list.print();
}
}
测试用例输出
扩展
数组遍历的逻辑由调用者自定义,而不是直接写死在print()中,如何实现?
以上的代码和动态数组(动态扩容)还没关系,感兴趣的朋友可以自己先实现下。
最后
好了,如果对你有帮助的话,欢迎点个免费的赞哦。