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

运行结果

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

相关推荐
慧都小妮子11 分钟前
Spire.PDF for .NET【页面设置】演示:打开 PDF 时自动显示书签或缩略图
java·pdf·.net
m512715 分钟前
LinuxC语言
java·服务器·前端
烦躁的大鼻嘎16 分钟前
模拟算法实例讲解:从理论到实践的编程之旅
数据结构·c++·算法·leetcode
IU宝20 分钟前
C/C++内存管理
java·c语言·c++
瓜牛_gn20 分钟前
依赖注入注解
java·后端·spring
hakesashou21 分钟前
Python中常用的函数介绍
java·网络·python
佚先森30 分钟前
2024ARM网络验证 支持一键云注入引流弹窗注册机 一键脱壳APP加固搭建程序源码及教程
java·html
C++忠实粉丝33 分钟前
计算机网络socket编程(4)_TCP socket API 详解
网络·数据结构·c++·网络协议·tcp/ip·计算机网络·算法
古月居GYH44 分钟前
在C++上实现反射用法
java·开发语言·c++
用户37791362947551 小时前
【循环神经网络】只会Python,也能让AI写出周杰伦风格的歌词
人工智能·算法