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

news2024/10/6 23:23:23

        前言:在 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.coloradmin.cn/o/1826731.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

深入理解计算机系统 CSAPP 家庭作业6.37

S256 N64时: sumA:这个很简单了,不说了 sumB:如下表. i递增时一直不命中 读到j1,i0 即读a[0][1]时 组0存放的是a[48][0] -a[48][3] 接着读a[1][1]时,组16放的是a[49][0]-a[49][3],j递增之后还是一直不命中 组0:a[0][0]a[16][0]a[32][0]a[48][0]a[0][1]组16:a[1][0]a[17][…

Python设计模式 - 简单工厂模式

定义 简单工厂模式是一种创建型设计模式&#xff0c;它通过一个工厂类来创建对象&#xff0c;而不是通过客户端直接实例化对象。 结构 工厂类&#xff08;Factory&#xff09;&#xff1a;负责创建对象的实例。工厂类通常包含一个方法&#xff0c;根据输入参数的不同创建并返…

训练营第三十八天 | 309.最佳买卖股票时机含冷冻期动态规划系列七总结714.买卖股票的最佳时机含手续费股票问题总结篇!

309.最佳买卖股票时机含冷冻期 力扣题目链接(opens new window) 给定一个整数数组&#xff0c;其中第 i 个元素代表了第 i 天的股票价格 。 设计一个算法计算出最大利润。在满足以下约束条件下&#xff0c;你可以尽可能地完成更多的交易&#xff08;多次买卖一支股票&#x…

泛微开发修炼之旅--15后端开发连接外部数据源,实现在ecology系统中查询其他异构系统数据库得示例和源码

文章链接&#xff1a;15后端开发连接外部数据源&#xff0c;实现在ecology系统中查询其他异构系统数据库得示例和源码

IT入门知识博客文章大纲(0/10)

IT入门知识博客文章大纲 引言 什么是IT&#xff1f; 信息技术&#xff08;Information Technology&#xff09;&#xff0c;互联网技术是指在计算机技术的基础上开发建立的一种信息技术 。互联网技术通过计算机网络的广域网使不同的设备相互连接&#xff0c;加快信息的传输速度…

STM32项目分享:车牌号识别系统

目录 一、前言 二、项目简介 1.功能详解 2.主要器件 三、原理图设计 四、PCB硬件设计 1.PCB图 2.PCB板打样焊接图 五、程序设计 六、实验效果 七、资料内容 项目分享 一、前言 项目成品图片&#xff1a; 哔哩哔哩视频链接&#xff1a; https://www.bilibili.…

MapReduce Simplified Data Processing on Large Clusters 论文笔记

2003年USENIX&#xff0c;出自谷歌&#xff0c;开启分布式大数据时代的三篇论文之一&#xff0c;作者是 Jeffrey 和 Sanjay&#xff0c;两位谷歌巨头。 Abstract MapReduce 是一种变成模型&#xff0c;用于处理和生成大规模数据。用户指定 map 函数处理每一个 key/value 对来…

手机上安装AI模型是一种什么体验?

昨天参加微软的AI DAY活动&#xff0c;看到微软的技术大佬分享了一个场景&#xff0c;就是坐飞机从上海到北京&#xff0c;机长广播因为天气原因&#xff0c;飞机需要盲降&#xff0c;他说当时听到盲降第一反应感觉有点恐慌&#xff0c;但是因为飞机上受限于网络环境&#xff0…

TIA博途中库类型和库元素的基本使用方法介绍

TIA博途中库类型和库元素的基本使用方法介绍 TIA博途中有两种不同类型的库: “项目库” “全局库” 内容由两种存储类型组成: • “类型” • “模板副本” (1) “项目库” – 集成在项目中,与项目一起管理 – 允许项目内可重复使用 (2) “全局库” – 独立库 – 可在…

MyBatis的逆向工程详细步骤操作

1. MyBatis的逆向工程详细步骤操作 文章目录 1. MyBatis的逆向工程详细步骤操作2. 逆向工程配置与生成2.1 MyBatis3Simple&#xff1a;基础版&#xff0c;只有基本的增删改查2.1.1 第一步&#xff1a;在pom.xml 中添加逆向工程插件2.1.2 第二步&#xff1a;配置 generatorConfi…

网络安全攻防基础入门笔记--操作系统名词解释文件下载反弹shell防火墙绕过

渗透测试常用专业术语 POC,EXP,Payload,Shellcode POC 全程Proof of Concept,中文"概念验证",常指一段漏洞证明的代码 EXP 全程Exploit ,中文"利用",指利用系统漏洞进行攻击的动作 Payload 中文"有效载荷",指成功Exploit之后,真正在目标系…

屹晶微EG3002 单通道功率MOSFET驱动芯片 贴片SOP8

EG3002作为一款功率MOSFET驱动芯片&#xff0c;它的应用领域主要取决于其技术参数和性能特点。根据之前提供的信息&#xff0c;EG3002可能适用于以下领域&#xff1a; 1. 电源管理&#xff1a;用于高效率电源转换器&#xff0c;如开关电源&#xff08;SMPS&#xff09;、电池充…

(虚拟机)VMware软件的安装及Ubuntu系统安装

一、VMware软件的安装 软件下载&#xff0c;可以自己找或者百度网盘下载&#xff1a; 通过百度网盘分享的文件&#xff1a;ubuntu16…等2个文件 链接:https://pan.baidu.com/s/1VEnZKY9DJ1T1vC3ae20gKQ 提取码:11b6 复制这段内容打开「百度网盘APP 即可获取」 1、解压VMwar…

进程的创建和管理

一. 实验内容 1&#xff0e; 编写一个程序&#xff0c;程序中创建一个子进程。然后父、子进程各自独立运行&#xff0c;父进程不断地在标准输出设备&#xff08;即显示器&#xff09;上输出字母p和回车&#xff08;输出30次或以上&#xff09;&#xff0c;子进程不断地在标准输…

MEMS:Lecture 17 Noise MDS

讲义 Minimum Detectable Signal (MDS) Minimum Detectable Signal&#xff08;最小可检测信号&#xff09;是指当信号-噪声比&#xff08;Signal-to-Noise Ratio, SNR&#xff09;等于1时的输入信号水平。简单来说&#xff0c;MDS 是一个系统能够分辨出信号存在的最低输入信号…

官方文档 搬运 MAXMIND IP定位 mysql导入 简单使用

官方文档地址&#xff1a; 官方文档 文件下载 1. 导入mysql可能报错 Error Code: 1290. The MySQL server is running with the --secure-file-priv option so it cannot execute this statement 查看配置 SHOW GLOBAL VARIABLES LIKE %secure%;secure_file_priv 原来…

vite-plugin-mock前端自行模拟接口返回数据的插件

vite-plugin-mock前端自行模拟接口返回数据的插件 安装导入、配置&#xff08;vite.config.js&#xff09;使用目录结构/mock/user.js具体在页面请求中的使用 注意事项 中文文档&#xff1a;[https://gitcode.com/vbenjs/vite-plugin-mock/blob/main/README.zh_CN.md) 参考其他…

区间预测 | Matlab实现BP-ABKDE的BP神经网络自适应带宽核密度估计多变量回归区间预测

区间预测 | Matlab实现BP-ABKDE的BP神经网络自适应带宽核密度估计多变量回归区间预测 目录 区间预测 | Matlab实现BP-ABKDE的BP神经网络自适应带宽核密度估计多变量回归区间预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.Matlab实现BP-ABKDE的BP神经网络自适应带…

深入理解计算机系统 CSAPP 家庭作业6.34

第一步先求(S,E,B,m) 题目说共C32个字节,块大小B为16个字节,那就是分为两组:0,1.然后每组存4个int 每个4字节 CB*E*S .B16 ,直接映射的E就是1,所以S2 m为啥等于7? 通过写出两个数组所有的地址可以得出m7. 得出高速缓存的参数:(S,E,B,m)(2,1,16,7),注意图6-26每个参数的定义…

官网首屏:太漂亮了,真是着了它的魔,上了它的道。

大气的企业官网致力于提供用户友好的界面和优质的用户体验。网页经过精心设计和开发&#xff0c;旨在展示客户的品牌形象和产品信息&#xff0c;并为用户提供便捷的服务和沟通渠道。 官网设计追求简洁、美观、易用的原则&#xff0c;以吸引用户的注意力并提供清晰的导航和信息…