动态数组的实现(仿写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. 提供了有参和无参构造
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);
    }
}

扩容/缩容

    // 扩容/缩容
    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实现

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

	// 删除尾部元素
    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;
    }
    // 删除中间元素
    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

// 查询
    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

    public Integer size() {
        return size;
    }

isEmpty

    public boolean isEmpty() {
        return size == 0;
    }

测试


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();
    }
}

运行结果

在这里插入图片描述

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/679868.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

浅析Vue3基础知识(vue3笔记之入门篇)

本文是结合实践中和学习技术文章总结出来的笔记(个人使用),如有雷同纯属正常((✿◠‿◠)) 喜欢的话点个赞,谢谢! 时下Vue框架都是使用Vue3版本来开发项目了,为了加深对Vue3基本知识的了解,特写了这个笔记 1. 生命周期 1.1. vue3生命周期 一个组件从开始到结束,正常的生命周…

【免费】2021年数学建模国赛C题问题一--基于熵权法和TOPSIS法详细版附Word加代码

各位大佬好 &#xff0c;这里是阿川的博客&#xff0c;祝您变得更强 个人主页&#xff1a;在线OJ的阿川 大佬的支持和鼓励&#xff0c;将是我成长路上最大的动力 阿川水平有限&#xff0c;如有错误&#xff0c;欢迎大佬指正 Python 初阶 Python–语言基础与由来介绍 Python–…

EXCEL多sheet添加目录跳转

EXCEL多sheet添加目录跳转 背景 excel中有几十个sheet&#xff0c;点下方左右切换sheet太耗时&#xff0c;希望可以有根据sheet名超链接跳转相应sheet&#xff0c;处理完后再跳回原sheet。 方案一 新建目录sheet&#xff0c;在A1写sheet名&#xff0c;右键选择最下方超链接…

I.MX RT1170之MIPI CSI摄像头初始化和显示流程详解

在上一篇文章I.MX RT1170之MIPI DSI初始化和显示流程详解中&#xff0c;我们介绍了RT1170单片机中MIPI DSI显示屏初始化和显示的详细步骤&#xff0c;那这一节就来介绍MIPI的另一个接口应用&#xff1a;摄像头CSI的初始化和配置流程。 对于摄像头来说&#xff0c;一般我们还要…

软件产品必须要进行鉴定测试吗?测试流程和作用简析

软件产品是现代社会中不可或缺的一部分&#xff0c;它们在商业、娱乐、科技等领域的应用广泛且深入。然而&#xff0c;我们是否关注过这些软件产品的鉴定测试呢?鉴定测试是什么?它的测试流程有哪些?又有什么作用呢?在本文中&#xff0c;我们将为您全面解析这些问题。 鉴定…

大数据学习问题记录

问题记录 node1突然无法连接finalshell node1突然无法连接finalshell 今天我打开虚拟机和finalshell的时候&#xff0c;发现我的node1连接不上finalshell,但是node2、node3依旧可以链接&#xff0c;我在网上找了很多方法&#xff0c;但是是关于全部虚拟机连接不上finalshell&a…

USB HOST DWC3 初始化

https://www.cnblogs.com/newjiang/p/15675746.html 如果dr_mode为device&#xff0c;则初始化gadget。 如果dr_mode为host&#xff0c;需要初始化xHCI驱动。在dwc3_host_init函数的最后调用platform_device_add(xhci)添加platform device&#xff08;xhci-hcd&#xff09;&a…

从当当网批量获取图书信息

爬取当当网图书数据并保存到本地&#xff0c;使用request、lxml的etree模块、pandas保存数据为excel到本地。 爬取网页的url为&#xff1a; http://search.dangdang.com/?key{}&actinput&page_index{} 其中key为搜索关键字&#xff0c;page_index为页码。 爬取的数据…

(九)Spring教程——ApplicationContext中Bean的生命周期

1.前言 ApplicationContext中Bean的生命周期和BeanFactory中的生命周期类似&#xff0c;不同的是&#xff0c;如果Bean实现了org.springframework.context.ApplicationContextAware接口&#xff0c;则会增加一个调用该接口方法setApplicationContext()的步骤。 此外&#xff0c…

[数据集][图像分类]蘑菇分类数据集3122张215类别

数据集类型&#xff1a;图像分类用&#xff0c;不可用于目标检测无标注文件 数据集格式&#xff1a;仅仅包含jpg图片&#xff0c;每个类别文件夹下面存放着对应图片 图片数量(jpg文件个数)&#xff1a;3122 分类类别数&#xff1a;215 类别名称:[“almond_mushroom”,“amanita…

C# 中文字符串转GBK字节的示例

一、编写思路 在 C# 中&#xff0c;将中文字符串转换为 GBK 编码的字节数组需要使用 Encoding 类。然而&#xff0c;Encoding 类虽然默认并不直接支持 GBK 编码&#xff0c;但是可以通过以下方式来实现这一转换&#xff1a; 1.使用系统已安装的编码提供者&#xff08;如果系统…

【Spring Cloud Alibaba】开源组件Sentinel

目录 什么是Sentinel发展历史与Hystrix的异同 Sentinel可以做什么&#xff1f;Sentinel的功能Sentinel的开源生态Sentinel的用户安装Sentinel控制台预备环境准备Sentinel 分为两个部分:下载地址 项目集成Sentinel创建项目修改依赖信息添加启动注解添加配置信息在控制器类中新增…

Java 新手入门:基础知识点一览

Java 新手入门&#xff1a;基础知识点一览 想要踏入 Java 的编程世界&#xff1f;别担心&#xff0c;这篇文章将用简单易懂的表格形式&#xff0c;带你快速了解 Java 的基础知识点。 一、Java 是什么&#xff1f; 概念解释Java一种面向对象的编程语言&#xff0c;拥有跨平台、…

最新PHP众筹网站源码 支持报名众筹+商品众筹+公益众筹等多种众筹模式 含完整代码包和部署教程

在当今互联网飞速发展的时代&#xff0c;众筹模式逐渐成为了创新项目、商品销售和公益活动融资的重要渠道。分享一款最新版的PHP众筹网站源码&#xff0c;支持报名众筹、商品众筹和公益众筹等多种众筹模式。该源码包含了完整的代码包和详细的部署教程&#xff0c;让新手也可以轻…

机器学习:算法到底学到了什么?

梯度下降算法 初始化参数 θ 0 \theta^0 θ0可以训练 MAML Maml和pre-train的区别是Maml用到了标注数据 把不同任务的数据放一起进行训练一个模型&#xff0c;当作Maml的baseline 领域迁移迁移学习 Maml好的原因 优化器也可以被学习 网络架构搜索 数据增强 样本权重分配 除…

创建自己的sdk

要把造轮子当作一种享受 右键class出来这个界面,在里面勾选静态库(.lib) 代码如下,我们要将其封装为一个sdk供别人安装使用 cpp文件如下 头文件如下,namespace可以写在头文件里面声明 生成 将那两个文件移到那个文件夹中 我们拿到生成的这两个文件了 截下来演示怎么导入到另…

docker-compose部署 kafka 3.7 启用账号密码认证

文章目录 1. 部署1.1 创建工作目录1.2 yml文件1&#xff09;文件内容2&#xff09;说明&#xff1a; 1.3 启动 2. 测试2.1 kafkamap搭建&#xff08;测试工具&#xff09;2.2 权限测试 1. 部署 1.1 创建工作目录 创建kafka目录&#xff0c;进入该目录 1.2 yml文件 1&#x…

Docker中搭建likeadmin

一、使用Docker中的docker-compose搭建likeadmin 1.去网址&#xff1a;https://gitee.com/likeadmin/likeadmin_php中下载likeadmin 注册一个giee账号后 点那个克隆下载 按照序号在终端复制粘贴进去。 接着&#xff0c;输入ls 可以发现有一个这个&#xff1a; 里面有一个like…

Cell|3D病理弱监督模型在前列腺癌患者治疗中的应用|顶刊精析·24-06-04

小罗碎碎念 这篇文章我之前分析过一遍&#xff0c;本期在原有基础上进行修改。 在正式阅读之前&#xff0c;小罗友情提醒大家重点关注一下几个方向&#xff1a; 从2D组织切片计算的TLS面积已被验证为多种肿瘤类型的预后和免疫治疗响应的生物标志物&#xff0c;然而在小样本活检…

ToxVidLLM:一个用于检测有害视频的多模态多任务框架

在一个社交媒体平台赋予用户成为内容创作者力量的时代&#xff0c;数字领域见证了前所未有的信息传播激增&#xff0c;到2023年&#xff0c;近82%的互联网流量是视频内容。因此&#xff0c;像抖音和YouTub这样的平台已经成为主要的信息来源。一个显著的统计数据凸显了这些平台的…