动态数组的实现(仿写ArrayList)

动态数组是什么

之前写过一篇数组和静态数组的介绍:数组的定义和特点,静态数组CURD的实现

我们在静态数组的基础上,增加一些比较方便的功能,比如自动扩容,获取数组长度等,这样的数组叫动态数组

动态数组的本质仍旧是静态数组,静态数组的特点它都有,只不过通过一些标记的变量新增了一些方法,方便我们进行CURD而已

相比于静态数组新增的功能

  1. 自动缩扩容
  2. addLast,add
  3. deleteLast,delete
  4. get,set(修改)
  5. size
  6. isEmpty

初始化动态数组

  1. 使用泛型可以创建任意类型的数组
  2. data即为真实的数组存放空间所在
  3. size是数组中存放数据的数量,初始为1
  4. INIT_CAPACITY 是默认的数组长度
  5. 提供了有参和无参构造
java 复制代码
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);
    }
}

扩容/缩容

java 复制代码
    // 扩容/缩容
    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实现

java 复制代码
    // 尾部增
    public void addLast(E e) {
        int l = this.data.length;
        if (size == l) {
            resize(2 * l);
        }
        // 在尾部插入元素
        data[size] = e;
        size++;
    }
java 复制代码
    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实现

java 复制代码
	// 删除尾部元素
    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;
    }
java 复制代码
    // 删除中间元素
    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

java 复制代码
// 查询
    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

java 复制代码
    public Integer size() {
        return size;
    }

isEmpty

java 复制代码
    public boolean isEmpty() {
        return size == 0;
    }

测试

java 复制代码
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();
    }
}

运行结果

我们可以很清楚的看到扩容和缩容,删除和新增等操作的实现

相关推荐
有梦想的攻城狮2 小时前
maven中的maven-antrun-plugin插件详解
java·maven·插件·antrun
CM莫问3 小时前
<论文>(微软)WINA:用于加速大语言模型推理的权重感知神经元激活
人工智能·算法·语言模型·自然语言处理·大模型·推理加速
计信金边罗5 小时前
是否存在路径(FIFOBB算法)
算法·蓝桥杯·图论
MZWeiei5 小时前
KMP 算法中 next 数组的构建函数 get_next
算法·kmp
硅的褶皱5 小时前
对比分析LinkedBlockingQueue和SynchronousQueue
java·并发编程
MoFe15 小时前
【.net core】天地图坐标转换为高德地图坐标(WGS84 坐标转 GCJ02 坐标)
java·前端·.netcore
季鸢6 小时前
Java设计模式之观察者模式详解
java·观察者模式·设计模式
Fanxt_Ja6 小时前
【JVM】三色标记法原理
java·开发语言·jvm·算法
luofeiju6 小时前
行列式的性质
线性代数·算法·矩阵
緈福的街口6 小时前
【leetcode】347. 前k个高频元素
算法·leetcode·职场和发展