Java中ArrayList(顺序表)的自我实现(如果想知道Java中怎么自我实现ArrayList,那么只看这一篇就足够了!)

        前言:在 Java 编程中,ArrayList 是一种非常常用的数据结构,它提供了动态数组的实现方式,可以方便地存储和操作数据。相比于传统的数组,ArrayList 具有更多的灵活性和便利性,可以根据需要动态地调整大小,并提供了一系列丰富的方法来增删改查元素,但是本篇文章主要讲解如何去自我实现Java中ArrayList(顺序表)。


✨✨✨这里是秋刀鱼不做梦的BLOG

✨✨✨想要了解更多内容可以访问我的主页秋刀鱼不做梦-CSDN博客

先让我们看一下本文的大致内容:

目录

1.自我定义ArrayList类

2.自我实现ArrayList中的方法

        (1)新增元素,默认在数组最后新增

        (2)在 pos 位置新增元素

        (3)判定是否包含某个元素

        (4)查找某个元素对应的位置

        (5)获取 pos 位置的元素

        (6)给 pos 位置的元素设为 value

        (7)删除第一次出现的关键字key

        (8)获取顺序表长度

        (9)打印顺序表

3.总结自我实现ArrayList


1.自我定义ArrayList类

        在自我实现Java中的ArrayList(顺序表)之前,我们需要先自我定义一个ArrayList类,定义方式如下:

public class MyArrayList{

    //创建一个数组
    private int[] array;

    //用于记录数组中的元素格式
    private int arrayNumber;

    //初始化数组原始大小
    public static final int CAPACITY = 10;

    //构造方法
    public MyArrayList() {
        this.array = new int[CAPACITY];
        this.arrayNumber = 0;
}

        这段代码定义了一个名为MyArrayList的类,用于实现顺序表。以下是对代码的分析:

  1. 私有属性:

    • array:一个整型数组,用于存储元素。

    • arrayNumber:一个整型变量,用于记录数组中元素的个数。

    • CAPACITY:一个常量,表示数组的初始容量。

  2. 构造方法:

    • MyArrayList():构造方法初始化了数组array为长度为CAPACITY的整型数组,并将arrayNumber初始化为0。

这样我们就定义好了一个ArrayList类,接下来就是实现Java中ArrayList中的方法了。

2.自我实现ArrayList中的方法

        在自我实现ArrayList中的方法之前,先让我们看一下要实现哪些方法:

// 新增元素,默认在数组最后新增
public void add(int data) { }
 
// 在 pos 位置新增元素
public void add(int pos, int data) { }
 
// 判定是否包含某个元素
public boolean contains(int toFind) { }
 
// 查找某个元素对应的位置
public int indexOf(int toFind) { }
 
// 获取 pos 位置的元素
public int get(int pos) { }
 
// 给 pos 位置的元素设为 value
public void set(int pos, int value) { }
 
//删除第一次出现的关键字key
public void remove(int toRemove) { }
 
// 获取顺序表长度
public int size() { }
 
// 打印顺序表
public void display() { }

那么接下来让我们一个一个的自我实现:

        (1)新增元素,默认在数组最后新增

Java代码:

    public boolean isFull() {
        return this.array.length == this.arrayNumber;
    }

    private void beBig() {
        this.array = Arrays.copyOf(this.array, this.array.length * 2);
    }

    public void add(int data) {
        //判断是否已满
        if (isFull()) {
            //顺序表满了就进行扩容
            beBig();
        }
        //顺序表未满,添加元素
        this.array[this.arrayNumber] = data;
        this.arrayNumber++;
    }

  现在我们对这些代码进行分析:

  1. isFull() 方法用于检查顺序表是否已满。它通过比较数组的长度和数组中元素的个数来确定是否满了。如果数组的长度等于数组中元素的个数(即 array.length == arrayNumber),则表示数组已满,返回 true;否则返回 false

  2. beBig() 方法用于扩容数组。它使用 Arrays.copyOf() 方法将原数组扩容为原来的两倍大小。这样做是为了在顺序表满时能够动态扩展数组大小以容纳更多的元素。

  3. add(int data) 方法用于向顺序表中添加元素。首先,它检查顺序表是否已满,如果满了,则调用 beBig() 方法进行扩容。然后,将新元素添加到数组的下一个位置,并更新数组中元素的个数。

        (2)在 pos 位置新增元素

Java代码:

    public boolean isFull() {
        return this.array.length == this.arrayNumber;
    }

    private void beBig() {
        this.array = Arrays.copyOf(this.array, this.array.length * 2);
    }


    public void add(int pos, int data) throws IndexException {
        //如果索引异常就抛出异常
        if (pos < 0 || pos > this.arrayNumber) {
            throw new IndexException("索引异常!!!");
        } else {
            //判断是否已满
            if (isFull()) {
                对原顺序表进行扩容
                beBig();
            } else {
                for (int i = this.arrayNumber - 1; i >= pos; i--) {
                    this.array[i + 1] = this.array[i];
                }
                this.array[pos] = data;
                this.arrayNumber++;
            }
        }
    }

现在让我们逐行分析一下:

  1. public boolean isFull(): 这个方法检查数组是否已满,即数组中的元素数量是否等于数组的长度。如果是,则返回true,否则返回false。

  2. private void beBig(): 这个方法用于扩大数组的容量。它使用Arrays.copyOf()方法创建了一个新数组,长度是原数组的两倍,然后将原数组的内容复制到新数组中。

  3. public void add(int pos, int data) throws IndexException: 这是一个添加元素的方法,接受两个参数:要添加的位置pos和要添加的数据data。如果位置超出了数组的范围,则抛出IndexException异常。否则,如果数组已满,则先扩大数组的容量,然后执行插入操作;如果数组未满,则将从插入位置开始的元素向后移动一个位置,为新元素腾出位置,并将新元素插入到指定位置。

        (3)判定是否包含某个元素

Java代码:

public boolean contains(int toFind) {
        //循环遍历顺序表查找目标元素
        for (int i = 0; i < this.arrayNumber; i++) {
            if (this.array[i] == toFind) {
                return true;
            }
        }
        return false;
    }

现在让我们来逐步分析一下:

  1. 方法签名:public boolean contains(int toFind)

    • 返回类型:boolean,表示是否包含特定元素。

    • 参数:int toFind,表示要查找的元素值。

  2. 循环结构:

    • 使用 for 循环遍历整数数组。

    • 循环变量 i 从 0 开始逐渐增加,直到数组长度(this.arrayNumber)。

  3. 条件判断:

    • 在每次循环中,通过 if 语句检查当前数组元素是否等于要查找的元素 toFind

    • 如果找到了匹配的元素,返回 true,表示数组中包含了要查找的元素。

  4. 返回结果:

    • 如果整个循环执行完毕都没有找到匹配的元素,则返回 false,表示数组不包含要查找的元素。

        (4)查找某个元素对应的位置

Java代码:

public int indexOf(int toFind) {
        //遍历顺序表查找元素位置
        for (int i = 0; i < this.arrayNumber; i++) {
            if (this.array[i] == toFind) {
                return i;
            }
        }
        return -1;
    }

让我逐行解释一下:

  1. public int indexOf(int toFind) {: 这是一个公有方法,用于查找数组中某个特定元素的索引。方法的参数 toFind 是要查找的目标元素。

  2. for (int i = 0; i < this.arrayNumber; i++) {: 这是一个 for 循环,从数组的第一个元素开始逐个检查,直到数组的长度为止。this.arrayNumber 可能是数组的长度,尽管代码中未显示出来,但我们可以假设它是这样的。

  3. if (this.array[i] == toFind) {: 在循环的每一次迭代中,检查数组中当前位置的元素是否等于我们要查找的元素 toFind

  4. return i;: 如果找到了匹配的元素,就返回当前元素的索引 i

  5. return -1;: 如果整个数组都被遍历了但没有找到匹配的元素,则返回 -1,表示未找到。

        (5)获取 pos 位置的元素

Java代码:

public boolean isEmpty() {
        return this.arrayNumber == 0;
    }

    public int get(int pos) throws EmptyException, IndexException {
        //判断数组是否为空
        if (isEmpty()) {
            throw new EmptyException("数组为空!!!");
        }
        //判断数组索引是否越界
        if (pos < 0 || pos >= this.arrayNumber) {
            throw new IndexException("索引异常!!!");
        }
        return this.array[pos];
    }

现在让我逐行解释一下:

  1. isEmpty() 方法用于检查数组是否为空。它通过检查 arrayNumber 属性是否为 0 来判断数组是否为空。如果 arrayNumber 为 0,则返回 true,否则返回 false

  2. get(int pos) 方法用于获取数组中指定位置的元素。它首先调用 isEmpty() 方法来检查数组是否为空。如果数组为空,则抛出 EmptyException 异常,表示数组为空。然后,它检查所请求的位置是否有效,即是否在数组范围内。如果位置 pos 小于 0 或者大于等于 arrayNumber,则抛出 IndexException 异常,表示索引异常。如果以上两个条件都通过了,它返回数组中位置 pos 的元素值。

        (6)给 pos 位置的元素设为 value

Java代码:

public boolean isEmpty() {
        return this.arrayNumber == 0;
    }

    public void set(int pos, int value) throws EmptyException, IndexException {
        //判断数组是否为空
        if (isEmpty()) {
            //抛出异常
            throw new EmptyException("数组为空!!!");
        }
        //判断数组索引是否越界
        if (pos < 0 || pos >= this.arrayNumber) {
            //抛出异常
            throw new IndexException("索引异常!!!");
        }
        this.array[pos] = value;
    }

现在让我逐行解释一下:

  1. isEmpty() 方法用于判断数组是否为空。它返回一个布尔值,表示数组中是否没有元素。具体来说,它通过检查数组中存储的元素数量是否为0来确定数组是否为空。

  2. set(int pos, int value) 方法用于设置数组中指定位置的元素值。它接受两个参数:位置(pos)和要设置的值(value)。在设置之前,它会先检查数组是否为空,如果为空则抛出 EmptyException 异常;然后检查位置是否合法,如果位置越界则抛出 IndexException 异常;最后,如果一切正常,它会将给定的值设置到指定位置的数组元素中。

        (7)删除第一次出现的关键字key

Java代码:

public boolean isEmpty() {
        return this.arrayNumber == 0;
    }

    public void remove(int toRemove) throws EmptyException{
        //判断数组是否为空
        if(isEmpty()){
            //抛出异常
            throw new EmptyException("数组为空!!!");
        }
        //遍历查找目标元素
        int index = indexOf(toRemove);
        if(index == -1){
            return;
        }
        for(int i = index;i<this.arrayNumber-1;i++){
            this.array[i] = this.array[i+1];
        }
        this.arrayNumber--;
    }

现在让我逐行解释一下:

  1. isEmpty() 方法:这个方法用于检查数组是否为空。它通过检查 arrayNumber 是否等于 0 来确定数组是否为空。如果 arrayNumber 为 0,则返回 true,表示数组为空,否则返回 false

  2. remove(int toRemove) 方法:这个方法用于从数组中删除指定的元素 toRemove。首先,它会检查数组是否为空,如果数组为空,则抛出 EmptyException 异常。然后,它会调用 indexOf(toRemove) 方法来查找 toRemove 在数组中的索引位置。如果找不到目标元素,则直接返回,不做任何操作。如果找到了目标元素,则会从该索引位置开始,将后面的元素向前移动一位,覆盖掉要删除的元素。最后,将数组的元素数量 arrayNumber 减一,表示成功删除了一个元素。

        (8)获取顺序表长度

Java代码:

public int size() {
        return this.arrayNumber;
    }

这里不做过多的解释了!!!

        (9)打印顺序表

Java代码:

public void display() {
        //循环遍历输出
        for (int i = 0; i < this.arrayNumber; i++) {
            System.out.print(this.array[i] + " ");
        }
    }

这里就是最简单的循环遍历数组,将数组中的元素进行输出操作。

        这样我们就完成了顺序表中所有的方法的自我实现了,当然读者还可以自己为这个自我实现的顺序表添加一下方法。

3.总结自我实现ArrayList

        从上边的文章中,我们自我创建了一个ArrayList,并且自我去实现了其中的方法,所以我们对上文进行一些总结,对于自我实现一个类似于ArrayList的数据结构的流程可以概括如下:

  1. 确定数据结构:选择合适的数据结构来存储元素。通常使用数组作为基础数据结构。

  2. 定义类和成员变量:创建一个类来表示 ArrayList,定义数组作为存储元素的数据结构,并定义一个表示数组当前大小的变量。

  3. 实现构造方法:编写构造方法初始化数组和其他必要的变量。

  4. 实现添加元素方法:编写方法来添加新的元素到数组中。需要考虑数组已满时的动态扩容。

  5. 实现获取元素方法:编写方法通过索引获取数组中的元素。

  6. 实现删除元素方法:编写方法来删除指定位置的元素。需要考虑删除元素后,保持数组的连续性。

  7. 实现其他操作方法:根据需要实现其他方法,如获取数组大小、清空数组、判断数组是否为空等。

  8. 异常处理:考虑可能出现的异常情况,如访问空数组、越界访问等,并进行适当的异常处理。

最后,我们附上自我实现的ArrayList的类的完整代码:

public class MyArrayList {
    private int[] array;
    private int arrayNumber;
    public static final int CAPACITY = 10;

    //构造方法
    public MyArrayList() {
        this.array = new int[CAPACITY];
        this.arrayNumber = 0;
    }

    public boolean isFull() {
        return this.array.length == this.arrayNumber;
    }

    private void beBig() {
        this.array = Arrays.copyOf(this.array, this.array.length * 2);
    }

    public void add(int data) {
        //判断是否已满
        if (isFull()) {
            //顺序表满了就进行扩容
            beBig();
        }
        //顺序表未满,添加元素
        this.array[this.arrayNumber] = data;
        this.arrayNumber++;
    }

    public void display() {
        for (int i = 0; i < this.arrayNumber; i++) {
            System.out.print(this.array[i] + " ");
        }
    }

    public void add(int pos, int data) throws IndexException {
        if (pos < 0 || pos > this.arrayNumber) {
            throw new IndexException("索引异常!!!");
        } else {
            if (isFull()) {
                beBig();
            } else {
                for (int i = this.arrayNumber - 1; i >= pos; i--) {
                    this.array[i + 1] = this.array[i];
                }
                this.array[pos] = data;
                this.arrayNumber++;
            }
        }
    }

    public boolean contains(int toFind) {
        for (int i = 0; i < this.arrayNumber; i++) {
            if (this.array[i] == toFind) {
                return true;
            }
        }
        return false;
    }

    public int indexOf(int toFind) {
        for (int i = 0; i < this.arrayNumber; i++) {
            if (this.array[i] == toFind) {
                return i;
            }
        }
        return -1;
    }

    public boolean isEmpty() {
        return this.arrayNumber == 0;
    }

    public int get(int pos) throws EmptyException, IndexException {
        //判断数组是否为空
        if (isEmpty()) {
            throw new EmptyException("数组为空!!!");
        }
        //判断数组索引是否越界
        if (pos < 0 || pos >= this.arrayNumber) {
            throw new IndexException("索引异常!!!");
        }
        return this.array[pos];
    }

    public void set(int pos, int value) throws EmptyException, IndexException {
        //判断数组是否为空
        if (isEmpty()) {
            //抛出异常
            throw new EmptyException("数组为空!!!");
        }
        //判断数组索引是否越界
        if (pos < 0 || pos >= this.arrayNumber) {
            //抛出异常
            throw new IndexException("索引异常!!!");
        }
        this.array[pos] = value;
    }

    public void remove(int toRemove) throws EmptyException {
        //判断数组是否为空
        if (isEmpty()) {
            //抛出异常
            throw new EmptyException("数组为空!!!");
        }
        //遍历查找目标元素
        int index = indexOf(toRemove);
        if (index == -1) {
            return;
        }
        for (int i = index; i < this.arrayNumber - 1; i++) {
            this.array[i] = this.array[i + 1];
        }
        this.arrayNumber--;
    }

    public int size() {
        return this.arrayNumber;
    }
    
}

关于Java中顺序表的使用------------------------------------------------------------------------------------>Java数据结构之ArrayList(如果想知道Java中有关ArrayList的知识点,那么只看这一篇就足够了!)-CSDN博客


以上就是本片文章的全部内容了~~~

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

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

相关文章

构建 deno/fresh 的 docker 镜像

众所周知, 最近 docker 镜像的使用又出现了新的困难. 但是不怕, 窝们可以使用曲线救国的方法: 自己制作容器镜像 ! 下面以 deno/fresh 举栗, 部署一个简单的应用. 目录 1 创建 deno/fresh 项目2 构建 docker 镜像3 部署和测试4 总结与展望 1 创建 deno/fresh 项目 执行命令…

嵌套查询(一)-谓词IN、量词ANY、量词ALL

一、在多个表之间进行数据查询&#xff0c;除了可以使用连接查询之外&#xff0c;也可以使用嵌套查询&#xff0c;那么什么是嵌套查询呢&#xff1f;如何使用嵌套查询呢&#xff1f; 1、将一个SELECT-FROM查询&#xff0c;嵌套在另一个SELECT查询语句中&#xff0c;那么这个SE…

响应式企业网站建站系统源码 模版丰富+一站式建站 全开源可二次开发 带源码包+搭建部署教程

系统概述 在数字化转型的浪潮中&#xff0c;企业官网作为品牌展示、产品推广及客户服务的重要窗口&#xff0c;其建设质量直接影响着企业的线上形象与市场竞争力。响应式企业网站建站系统源码的出现&#xff0c;为企业提供了一种高效、灵活且成本可控的建站解决方案。 代码示…

【安装笔记-20240612-Linux-内网穿透服务之cpolar极点云】

安装笔记-系列文章目录 安装笔记-20240612-Linux-内网穿透服务之 cpolar 极点云 文章目录 安装笔记-系列文章目录安装笔记-20240612-Linux-内网穿透服务之 cpolar 极点云 前言一、软件介绍名称&#xff1a;cpolar极点云主页官方介绍 二、安装步骤测试版本&#xff1a;openwrt-…

日本旅游回忆录Day1-02三千院

中午回到京都站吃拉面啦&#xff0c;这边的图片由小宝补充&#xff0c;整体味道是不错的啦。时间关系&#xff0c;我不展开了&#xff0c;由小宝补充。 拉面&#xff1a; 下午目的地是三千院。 我们是坐公交车去的&#xff0c;刚刚上车就坐到了靠窗的位置&#xff0c;往深山里…

华为防火墙技术

防火墙技术综合介绍1 时代的认知&#xff1a;这是一个快鱼吃慢鱼的时代&#xff0c;是技术能够成就梦想是时代。 防火墙的认知&#xff1a;网络安全产品&#xff1b;位于网络的边界&#xff08;企事业单位的出口位置与ISP运营商进行连接并接入外网&#xff08;公网的&#xff…

MySQL(5)

聚合函数 GROUP BY 的使用 需求&#xff1a;查询各个部门的平均工资&#xff0c;最高工资SELECT department_id,AVG(salary),SUM(salary)FROM employeesGROUP BY department_id;需求&#xff1a;查询各个job_id的平均工资SELECT job_id,AVG(salary)FROM employeesGROUP BY jo…

rocketmq-5.1.2的dleger高可用集群部署

1、背景 原先为5.0.0版本&#xff0c;因检查出有漏洞&#xff0c;升级到5.1.2版本。 【Rocketmq是阿里巴巴在2012年开发的分布式消息中间件&#xff0c;专为万亿级超大规模的消息处理而设计&#xff0c;具有高吞吐量、低延迟、海量堆积、顺序收发等特点。在一定条件下&#xf…

牧原发布年度低碳报告,看行业“一哥”如何数字化减碳!

此前&#xff0c;牧原信息化负责人何秋梅在接受绿研院的专题访谈时提到&#xff1a;“在销售、采购等业务上&#xff0c;都涉及到大量的合同和文件&#xff0c;传统的纸质合同保存和管理繁琐&#xff0c;需要档案柜存储&#xff0c;且成本高昂。使用电子签不仅节省了打印、盖章…

优雅迷人的小程序 UI 风格

优雅迷人的小程序 UI 风格

什么是DMZ?路由器上如何使用DMZ?

文章目录 📖 介绍 📖🏡 演示环境 🏡📒 DMZ 📒🚀 DMZ的应用场景💡 路由器设置DMZ🎈 注意事项 🎈⚓️ 相关链接 ⚓️📖 介绍 📖 在网络管理中,DMZ(Demilitarized Zone,隔离区)是一个特殊的网络区域,常用于将公共访问和内部网络隔离开来。DMZ功能允许…

【Android面试八股文】1. 你说一说Handler机制吧 2. 你知道Handler的同步屏障吗? 3. Looper一直在循环,会造成阻塞吗?为什么?

文章目录 一. 你说一说Handler机制吧二、你知道Handler的同步屏障吗&#xff1f;2.1 Handler消息的分类2.2 什么是同步屏障2.3 为什么要设计同步屏障2.4 同步屏障的用法 三、Looper一直在循环&#xff0c;会造成阻塞吗&#xff1f;为什么&#xff1f;扩展阅读 一. 你说一说Hand…

大数据在商业中的应用——Kompas.ai如何助力企业决策

引言 在现代商业中&#xff0c;大数据逐渐成为企业决策的重要工具。通过对海量数据的分析和处理&#xff0c;企业可以获得重要的市场信息和决策支持。本文将探讨大数据在商业中的应用&#xff0c;并介绍Kompas.ai如何通过AI技术助力企业决策。 大数据的发展及其重要性 大数据…

项目文章 | Cell ReportsChIP-seq和RNA-seq联合鉴定伯克霍尔德氏菌毒性的重要调节因子

发表单位&#xff1a;中山大学深圳校区制药科学学院 发表日期&#xff1a;2024年5月14日 研究期刊&#xff1a;Cell Reports&#xff08;IF: 8.8&#xff09; 研究材料&#xff1a;伯克霍尔德氏菌 主要技术&#xff1a;ChIP-seq&#xff0c;EMSA&#xff0c;微尺度热泳分析…

1970-2021年各区县碳排放总量,可选择所需年份获取,shp/excel多种格式数据

基本信息. 数据名称: 1970-2021年各区县碳排放总量 数据格式: Shpexcel 数据几何类型: 面 数据坐标系: WGS84 数据来源&#xff1a;网络公开数据

Java面经总结

一、java基础 1.重载和重写的区别 重载&#xff1a; 发生在同一类中&#xff0c;函数名必须一样&#xff0c;参数类型、参数个数、参数顺序、返回值、修饰符可以不一样。重写&#xff1a; 发生在父子类中&#xff0c;函数名、参数、返回值必须一样&#xff0c;访问修饰符必须…

清晖项目管理资深企业咨询顾问闫清受邀为第十三届中国PMO大会演讲嘉宾

全国PMO专业人士年度盛会 清晖项目管理资深企业咨询顾问闫清女士受邀为PMO评论主办的2024第十三届中国PMO大会演讲嘉宾&#xff0c;演讲议题为“PMO的多重人工智能价值”。大会将于6月29-30日在北京举办&#xff0c;敬请关注&#xff01; 议题简要&#xff1a; 在近几年的AI概…

据阿谱尔统计显示,2023年全球凹版印刷机市场销售额约为9.1亿美元

根据阿谱尔 (APO Research&#xff09;的统计及预测&#xff0c;2023年全球凹版印刷机市场销售额约为9.1亿美元&#xff0c;预计在2024-2030年预测期内将以超过2.54%的CAGR&#xff08;年复合增长率&#xff09;增长。 由于对软包装和印刷包装的需求不断增长&#xff0c;全球凹…

前端问题整理

Vue vue mvvm&#xff08;Model-View-ViewModel&#xff09;架构模式原理 Model 是数据层&#xff0c;即 vue 实例中的数据View 是视图层&#xff0c; 即 domViewModel&#xff0c;即连接Model和Vue的中间层&#xff0c;Vue实例就是ViewModelViewModel 负责将 Model 的变化反映…

SpringCloud学习笔记 - 1、Boot和Cloud版本选型

文章目录 前言需要&#xff08;学习/用到&#xff09;的技术SpringBoot版本的选择我们为什么要使用 Java 17&#xff0c;以及SpringBoot 3.2 呢&#xff1f; SpringCloud 版本的选择SpringCloud 命名规则Springcloud Alibaba 版本的选择如何确定Boot&#xff0c;Cloud&#xff…