当前位置: 首页 > article >正文

手把手教你如何实现List——ArrayList

目录

前言:

 线性表

顺序表

  接口的实现

一. 打印顺序表

二.新增元素,默认在数组最后新增

三.在 pos 位置新增元素 

四.判定是否包含某个元素

 五. 查找某个元素对应的位置

 六.获取 pos 位置的元素

七.给 pos 位置的元素设为 value 

八.删除第一次出现的关键字key 

九.获取顺序表长度

十.清空顺序表 

ArrayList的遍历

ArrayList的问题及思考

前言:

什么是List?

在集合框架中,List是一个接口,继承自Collection。

站在数据结构的角度来看,List就是一个线性表,即n个具有相同类型元素的有限序列,在该序列上可以执行增删改查以及变量等操作。 

List中提供了好的方法,具体如下:

 

注意:List是个接口,并不能直接用来实例化。
如果要使用,必须去实例化List的实现类。在集合框架中,ArrayListLinkedList都实现了List接口。

本篇我们开始 ArrayList的学习


 线性表

线性表(linear list)是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列...

线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的,线性表在物理上存储时,通常以数组和链式结构的形式存储。


顺序表

顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储。在数组上完成数据的增删查改。

  接口的实现

先初始化数组 

有效数字现在为useSize 

模拟实现接口里面的所有的功能  也基本上就学会了顺序表的所有功能

实现在MyArrayList这个类中重写

一. 打印顺序表

 打印顺序表比较简单,知道它的userSize,遍历一遍就可以

public void display() {
        for (int i = 0; i < useSize ; i++) {
            System.out.print(elem[i] + "");
        }
        System.out.println();
    }

二.新增元素,默认在数组最后新增

思路: 直接找到userSize位置,直接赋值就行 有效数组userSize为4

假如我们需要添加5,直接在下标为4的位置上赋值

添加完userSize++

考虑问题要全,如果数组满了,我们需要给它扩容已被才可以添加 

所有得先判断是否数组满了,如果满了先扩容再添加

代码实现:

public void add(int data) {
        //判断
        if(useSize == 5) {
            elem = Arrays.copyOf(elem,elem.length*2);
        }
        //添加
        elem[useSize] = data;
        useSize++;
    }

 效果:


三.在 pos 位置新增元素 

 

在1下标添加11 

应该把1下标后面的元素往后面移动  从userSzie-1下标开始向右移动 

并且得先从最右边的元素开始移动

最后userSize++;

考虑情况:  

另外pos下标值不能小于0或者大于usersize

代码实现: 

 public void add(int pos, int data) {
        //先检查是否数组满了吗?
        if(useSize == 5) {
            elem = Arrays.copyOf(elem,elem.length*2);
        }
        // 判断pos是否合法
        if(pos < 0 || pos > useSize) {
            //抛出异常
            throw new PosException("pos未知不合法" + pos);
        }
        for (int i = useSize - 1; i >= pos ; i--) {
            elem[i+1] = elem[i];
        }
        elem[pos] = data;
        useSize++;
    }

 


四.判定是否包含某个元素

 

遍历整个数组,再判断

代码实现:  

   public boolean contains(int toFind) {
        for (int i = 0; i < useSize; i++) {
            if(elem[i] == toFind) {
                return true;
            }
        }
        return false;
    }

 五. 查找某个元素对应的位置

代码实现:  

   public int indexOf(int toFind) {
        for (int i = 0; i < useSize; i++) {
            if(elem[i] == toFind) {
                return i;
            }
        }
        return -1;
    }


 六.获取 pos 位置的元素

 

这里的pos不能等于userSize了,否则越界了 

代码实现:  

   public int get(int pos) {
         判断pos是否合法
        if(pos < 0 || pos >= useSize) {
            //抛出异常
            throw new PosException("pos未知不合法" + pos);
        }
        return elem[pos];
    }

七.给 pos 位置的元素设为 value 

代码实现:  

 public void set(int pos, int value) {
        // 判断pos是否合法
        if(pos < 0 || pos > useSize) {
            //抛出异常
            throw new PosException("pos未知不合法" + pos);
        }
        elem[pos] = value;
    }


八.删除第一次出现的关键字key 

 

先判断顺序表是否为空 空的不可以删除的

删除结束userSize-- 

 代码实现:  

    public void remove(int toRemove) {
        if(useSize == 0){
           throw new EmptyException("顺序表为空");
        }
        //获取toRemove下标
        int index = indexOf(toRemove);
        for (int i = index; i < useSize - 1 ; i++) {
            elem[i] = elem[i+1];
        }
        useSize--;
    }

九.获取顺序表长度

 public int size() {
        return useSize;
    }

十.清空顺序表 

 public void clear() {
        useSize = 0;
    }

 以上基本上就是顺序表所有的基本操作 


ArrayList的遍历

一:直接打印

 二:for循环遍历

三. for each遍历

 四.使用迭代器


ArrayList的问题及思考

1. ArrayList底层使用连续的空间,任意位置插入或删除元素时,需要将该位置后序元素整体往前或者往后搬移,故时间复杂度为O(N)
2. 增容需要申请新空间,拷贝数据,释放旧空间。会有不小的消耗。
3. 增容一般是呈2倍的增长,势必会有一定的空间浪费。例如当前容量为100,满了以后增容到200,我们再继续插入了5个数据,后面没有数据插入了,那么就浪费了95个数据空间。

当在ArrayList任意位置插入或者删除元素时,就需要将后序元素整体往前或者往后
搬移,时间复杂度为O(n),效率比较低,因此ArrayList不适合做任意位置插入和删除比较多的场景。

接下来我们会进行 LinkedList(链表)的学习


http://www.kler.cn/a/148961.html

相关文章:

  • 【大数据学习 | flume】flume的概述与组件的介绍
  • 数字后端教程之Innovus report_property和get_property使用方法及应用案例
  • 数据挖掘(九)
  • 设计模式之责任链模式(Chain Of Responsibility)
  • Microsoft 365 Exchange如何设置可信发件IP白名单
  • 21. Drag-Drop拖放操作(二) - 文件、表格和树的拖放实现
  • 鸿蒙(HarmonyOS)应用开发——应用程序入口UIAbility(题目答案)
  • C#,数值计算——插值和外推,径向基函数插值(RBF_inversemultiquadric)的计算方法与源程序
  • 基于binlog实现一些业务(Binlog4j)
  • 哈希表——闭散列表
  • 分析:为什么有些pdf打开之后无法编辑?
  • JVM运行时数据区域、对象内存分配、内存溢出异常总结
  • 将kali系统放在U盘中插入电脑直接进入kali系统
  • day64 django中间件的复习使用
  • 【赠书第9期】巧用ChatGPT高效搞定Excel数据分析
  • grep笔记231128 grep的 -e , -E , -F , -G , -P 有什么区别
  • 不同路径(力扣LeetCode)动态规划
  • MS1242/MS1243:24bit 高精度、低功耗模数转换器
  • 视频集中存储/磁盘阵列EasyCVR平台黑名单异常解决步骤是什么?
  • Unity之ARFoundation如何实现BodyTracking人体跟踪
  • Django二转Day02
  • qml ParticleSystem3D使用介绍
  • 记录ruoyi-plus-vue部署的问题
  • 华为设备使用python实现文件自动保存下载
  • 封装一些可能会用到的JS的Dom操作方法(非JS自带的方法)
  • Python小知识