前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >【Java】ArrayList的模拟实现详解!!!

【Java】ArrayList的模拟实现详解!!!

作者头像
喜欢做梦
发布2024-11-25 18:08:21
发布2024-11-25 18:08:21
9600
代码可运行
举报
文章被收录于专栏:学习
运行总次数:0
代码可运行

一、🍩简单了解ArrayList

什么是ArrayList? 在集合框架中,ArrayList是一个普通的类,其内部基于数组实现,数据存储有序,实现的List接口。List是一个接口不能进行实例化,而ArrayList实现了这个接口。

  • List就是一个线性表,即具有n个相同类型元素的有限序列,在该序列上可以执行增删查改的功能以及变量等操作。

二、🍩ArrayList的简单模拟实现

1.🍔IList接口

首先,我们知道ArrayList实现了List的接口,所以我们要知道List接口中有哪些方法,并且ArrayLiat要重写List接口中的方法这里我们对其是简单模拟ArrayList,我们实现其一些常见的功能就好。

ArrayList常见方法:

增:

void add(int data)

在数组最后添加元素

void add(int pos,int data)

在数组某下标插入元素

删:

void remove(int toRemove)

删除第一次出现的元素

void clear();

清空所有元素

查:

boolean contains(int toFind)

查看是否包含该元素

int get(int pos)

获取该下标元素

int indexOf(int toFind )

获取该元素下标

改:

void set(int pos,int value)

将下标元素进行更改

这些常见方法就是增删查改的功能。

1.🍕IList接口
代码语言:javascript
代码运行次数:0
复制
public interface IList {
    public void add(int data);
    public void add(int pos,int data);
    public void remove(int toRemove);
    public void clear();
    public boolean contains(int toFind);
    public int get(int pos);
    public int indexOf(int toFind);
    public void set(int pos,int value);
}
2. 🍕 MyArrayList 重写接口方法
代码语言:javascript
代码运行次数:0
复制
public class MyArrayList implements IList{
    @Override
    public void add(int data) {

    }
    @Override
    public void add(int pos, int data) {

    }
    @Override
    public void remove(int toRemove) {

    }
    @Override
    public void clear() {

    }
    @Override
    public boolean contains(int toFind) {
        return false;
    }
    @Override
    public int get(int pos) {
        return 0;
    }
    @Override
    public int indexOf(int toFind) {
        return 0;
    }
    @Override
    public void set(int pos, int value) {

    }
}

我们知道,ArrayList内部是基于数组内部实现, 并且他是一个有限序列,所以我们需要在MyArrayList中加几个定义的变量

代码语言:javascript
代码运行次数:0
复制
public class MyArrayList implements IList{
    public int[] array;
    //默认容量大小
    //这个为常量,所以可以使用static final
    public static final int DEFULATE_CAPACITY=10;
    //以占用的数组空间大小
    public int usedsize;
    //构造方法
    public MyArrayList() {
        this.array = new int[DEFULATE_CAPACITY];
    }
}

2.🍔ArrayList方法

1.🥪增

1.add(添加元素):添加在末尾

注意事项:

  • 是否空间已满,如果满了进行扩容;
  • 添加了代码之后,使用空间增加。
代码语言:javascript
代码运行次数:0
复制
public void add(int data) {
        //如果满了,进行扩容
        if(isFull()){
            grows();
        }
        //数组下标由0开始,在增加一个元素的时候,其下标在第usedsize的位置上
        array[usedsize]=data;
        usedsize++;
    }

判断空间是否已满(isFull):使用空间==空间大小

代码语言:javascript
代码运行次数:0
复制
    public boolean isFull(){
        return this.usedsize==array.length;
    }

扩容(grows):使用Arrays.copyOf进行扩容

代码语言:javascript
代码运行次数:0
复制
   public void grows(){
        this.array= Arrays.copyOf(this.array,
                2*this.array.length);
    }

为了更好的查看结果,我们需要加上一个打印方法

展示:注意这里的i是小于数组以使用的长度usedsize而不是数组的全部长度

代码语言:javascript
代码运行次数:0
复制
 public void display(){
        for (int i = 0; i < usedsize; i++) {
            System.out.print(array[i]+" ");
        }

测试:

代码语言:javascript
代码运行次数:0
复制
public class Test {
    public static void main(String[] args) {
        MyArrayList myArrayList=new MyArrayList();
        myArrayList.add(1);
        myArrayList.add(2);
        myArrayList.add(3);
        myArrayList.add(1);
        myArrayList.add(2);
        myArrayList.add(3);
        myArrayList.add(1);
        myArrayList.add(2);
        myArrayList.add(3);
        myArrayList.add(1);
        myArrayList.add(2);
        myArrayList.add(3);
        myArrayList.display();
    }
}

结果:

46705e0757ed4c279d1061b15072cff4.png
46705e0757ed4c279d1061b15072cff4.png

2.add(插入元素):插入元素在任意位置

注意事项: 1.插入元素的下标不能小于0以及不能大于usedsize,否则·报错; 2.插入空间是否已满,满了扩容; 3.已使用数组长度增加;

我们需要检查添加的下标位置是否合法,由于可能会出现位置不合法的情况,如果出现这种情况,要报错,所以我们需要自定义一个位置不合法异常

PosIlleagal类:继承运行时异常

代码语言:javascript
代码运行次数:0
复制
public class PosIllegal extends RuntimeException{
    public PosIllegal() {
        super();
    }
    public PosIllegal(String message) {
        super(message);
    }
}

出现异常条件:插入元素的下标不能小于0以及不能大于usedsize

checkPos:检查插入元素的下标是否合法

代码语言:javascript
代码运行次数:0
复制
  //throws:其提醒作用,可能存在的异常
    public void checkPos(int pos) throws PosIllegal{
        //如果下标位置不合法,报错
        if(pos < 0 || pos >= usedsize){
            throw new PosIllegal("位置不合法!!!");
        }
    }

既然可能会出现异常,我们需要对其进行try-catch捕获处理

代码语言:javascript
代码运行次数:0
复制
    public void add(int pos, int data) {
        try{
            checkPos(pos);
            if(isFull()){
                grows();
            }
        }catch (PosIllegal e){
            System.out.println("下标插入位置不合法");
            e.printStackTrace();
        }catch(Exception e){
            e.printStackTrace();
        }
    }

add(插入元素):我们可以从后往前,将前面的元素向后移动,直到移动到所需插入元素的下标为止,随即插入元素

代码语言:javascript
代码运行次数:0
复制
   public void add(int pos, int data) {
        try{
            checkPos(pos);
            if(isFull()){
                grows();
            }
            for (int i = usedsize-1; i >=pos ; i--) {
                array[i+1]=array[i];
            }
            array[pos]=data;
            usedsize++;
        }catch (PosIllegal e){
            System.out.println("下标插入位置不合法");
            e.printStackTrace();
        }catch(Exception e){
            e.printStackTrace();
        }
    }

测试:

代码语言:javascript
代码运行次数:0
复制
   public static void main(String[] args) {
        MyArrayList myArrayList=new MyArrayList();
        myArrayList.add(1);
        myArrayList.add(2);
        myArrayList.add(3);
        myArrayList.add(3,11);
        myArrayList.add(6,5);
        myArrayList.display();
    }

结果:

fc59e73a8d8a4178b69fd65218e840f5.png
fc59e73a8d8a4178b69fd65218e840f5.png
2.🥪 查

1.contains(是否包含该元素)

contains:遍历所使用的数组大小,查找是否有该元素

代码语言:javascript
代码运行次数:0
复制
    @Override
    public boolean contains(int toFind) {
        for (int i = 0; i < usedsize; i++) {
            if(array[i]==toFind){
                return true;
            }
        }
        return false;
    }

2.get(获取下标元素)

注意事项: 1.该数组是否为空,如果为空,报错 1.该下标是否合法,如果下标小于0或者下标大于等于usedsize,那么位置不合法; 注意:这里的是大于等于,插入元素的不合法是大于

既然我们在使用get方法的时候会出现顺序表为空的情况下,那么我们需要一个顺序表为空时候的异常

EmptyException(顺序表为空异常):

代码语言:javascript
代码运行次数:0
复制
public class EmptyException extends RuntimeException{
    public EmptyException() {
    }

    public EmptyException(String message) {
        super(message);
    }
}

checkEmpty(顺序表报错条件):

代码语言:javascript
代码运行次数:0
复制
   public void checkEmpty() throws EmptyException{
        if(usedsize==0){
            throw new EmptyException("顺序表为空");
        }
    }

由于这样的位置不合法条件与插入元素的位置不合法条件不同,所以我们需要再写一个检查位置是否合法的方法

checkPos2(检查pos位置是否合法):

代码语言:javascript
代码运行次数:0
复制
   public void checkPos2(int pos) throws PosIllegal{
        if(pos < 0 || pos >= usedsize){
            throw new PosIllegal("位置不合法!!!");
        }
    }

get:如果没有出现异常,直接返回下标元素

代码语言:javascript
代码运行次数:0
复制
public int get(int pos) {
        try {
            checkEmpty();
            checkPos2(pos);
            return array[pos];
        }catch (PosIllegal e){
            System.out.println("Pos位置不合法");
            e.printStackTrace();
        }catch (EmptyException e){
            System.out.println("顺序表为空");
            e.printStackTrace();
        }catch (Exception e){
            e.printStackTrace();
        }
        return -1;
    }

3.indexOf (获取元素下标)

注意事项: 1.是否包含该元素,如果没有返回-1;

indexOf:遍历数组元素,查找是否有该元素,有则返回元素下标,没有返回-1

代码语言:javascript
代码运行次数:0
复制
 public int indexOf(int toFind) {
        if(contains(toFind)){
            for (int i = 0; i < usedsize; i++) {
                if(array[i]==toFind){
                    return i;
                }
            }
        }
        return -1;
    }

测试:

代码语言:javascript
代码运行次数:0
复制
 public static void main(String[] args) {
        MyArrayList myArrayList=new MyArrayList();
        myArrayList.add(1);
        myArrayList.add(2);
        myArrayList.add(3);
        //是否包含
        boolean b=myArrayList.contains(5);
        System.out.println(b);//false
        //获取下标元素
        int a=myArrayList.get(2);
        System.out.println(a);//3
        //获取元素下标
        int c=myArrayList.indexOf(0);
        System.out.println(c);//-1
        int d=myArrayList.indexOf(3);
        System.out.println(d);//2
    }

结果:

f240ab6935054223bf12264339af1029.png
f240ab6935054223bf12264339af1029.png
3.🥪删

1.remove(删除元素)

注意事项: 1.顺序表是否为空; 2.是否有该元素; 3.如果删除完该元素,数组使用长度减小。

remove:获取下标,如果下标不存在,返回;如果下标存在,将下标从前往后遍历,将后面的元素向前移动

代码语言:javascript
代码运行次数:0
复制
public void remove(int toRemove) {
       try{
           checkEmpty();
           //获取下标
           int pos=indexOf(toRemove);
           if(pos==-1){
               System.out.println("没有该元素,移除失败");
               return;
           }
           //从前往后,将后面的元素向前移动
           //i是小于usedsize-1就好,因为当i=usedsize-2
           //将usedsize-1中的元素移到了usedsize-2中
           for (int i = pos; i < usedsize-1; i++) {
                  array[i]=array[i+1];
           }
           usedsize--;
       }catch (EmptyException e){
           System.out.println("顺序表为空");
           e.printStackTrace();
       }catch(Exception e){
           e.printStackTrace();
       }
    }

2.clear(清空所有元素)

clear:直接将使用空间置0;

代码语言:javascript
代码运行次数:0
复制
 public void clear() {
        this.usedsize=0;
    }

测试:

代码语言:javascript
代码运行次数:0
复制
    public static void main(String[] args) {
        MyArrayList myArrayList=new MyArrayList();
        myArrayList.add(1);
        myArrayList.add(2);
        myArrayList.add(3);
        myArrayList.display();
        System.out.println();//1 2 3
        //移除:
        myArrayList.remove(2);
        myArrayList.display();
        System.out.println();//1 3
        myArrayList.remove(5);//没有该元素,移除失败
        System.out.println();
        //清空:
        myArrayList.clear();
        myArrayList.display();
        myArrayList.add(1);
        myArrayList.display();//1
    }
c92016dd477e447bacf73d0d22e16471.png
c92016dd477e447bacf73d0d22e16471.png
4.🥪改

1.set(更改元素):将元素进行替换

注意事项: 1.顺序表是否为空; 2.进行更改的元素下标是否合法

set:直接将下标所对于的元素进行更改

代码语言:javascript
代码运行次数:0
复制
public void set(int pos, int value) {
        try{
            checkEmpty();
            checkPos2(pos);
            array[pos]=value;
        }catch (EmptyException e){
            System.out.println("顺序表为空");
            e.printStackTrace();
        }catch (PosIllegal e){
            System.out.println("下标位置不合法");
            e.printStackTrace();
        }catch(Exception e){
            e.printStackTrace();
        }
    }

测试:

代码语言:javascript
代码运行次数:0
复制
public static void main(String[] args) {
        MyArrayList myArrayList=new MyArrayList();
        myArrayList.add(1);
        myArrayList.add(2);
        myArrayList.add(3);
        myArrayList.display();//1 2 3
        System.out.println();
        myArrayList.set(2,11);//1 2 11
        myArrayList.display();
        System.out.println();
        myArrayList.set(5,11);//报错
        myArrayList.display();
    }

结果:

1eed3f969c7941038993ccabb945c328.png
1eed3f969c7941038993ccabb945c328.png
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-11-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、🍩简单了解ArrayList
  • 二、🍩ArrayList的简单模拟实现
    • 1.🍔IList接口
      • 1.🍕IList接口
      • 2. 🍕 MyArrayList 重写接口方法
    • 2.🍔ArrayList方法
      • 1.🥪增
      • 2.🥪 查
      • 3.🥪删
      • 4.🥪改
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档