动态数组的实现(仿写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();
    }
}

运行结果

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

相关推荐
天使day10 分钟前
SpringMVC
java·spring·java-ee
咒法师无翅鱼13 分钟前
【定理证明工具调研】Coq, Isabelle and Lean.
算法
CodeClimb28 分钟前
【华为OD-E卷-简单的自动曝光 100分(python、java、c++、js、c)】
java·python·华为od
风清云淡_A39 分钟前
【java基础系列】实现数字的首位交换算法
java·算法
Gao_xu_sheng41 分钟前
Java程序打包成exe,无Java环境也能运行
java·开发语言
涵涵子RUSH42 分钟前
合并K个升序链表(最优解)
算法·leetcode
大卫小东(Sheldon)1 小时前
Java的HTTP接口测试框架Gatling
java
谢家小布柔1 小时前
java中的继承
java·开发语言
爱吃西瓜的小菜鸡1 小时前
【C语言】矩阵乘法
c语言·学习·算法
l138494274511 小时前
Java每日一题(2)
java·开发语言·游戏