顺序表 ArrayList

简介: 顺序表 ArrayList

1. 概念

       ArrayList实现了List接口,它是在一个连续的储存块中储存元素,与数组不同的是,通过在序列尾部添加新的元素,ArrayList能进行动态的增长。顺序表一般情况下采用数组存储,在数组上完成数据的增删查改,并且访问其元素可以直接通过元素的索引直接访问和更新。

       注意:

  • ArrayList是一种动态数组。
  • ArrayList类是一种元素为Object引用的泛型集合。


2. ArrayList集合框架图

a344b4b28d124a609632db1a7d38c0ce.png

则:

  • ArrayList是泛型实现的,使用时必须进行实例化;
  • ArrayList实现了RandomAccess接口,则ArrayList支持随机访问;
  • ArrayList实现了Cloneabel接口,则ArrayList支持clone;

ArrayList实现了Serialzable接口,则ArrayList支持序列化;

和Vector不同,ArrayList不是线程安全的,在单线程下可以使用,在多线程中可以选择Vector或者CopyOnWriteArrayList


3.ArrayList常见的方法

方法         解释
add(E e) 尾插一个元素e
add(int index,E e) 在index位置插入e
remove(int index)

删除index位置的元素

remove(Object o)

删除第一个遇到的o

get(int index) 获得index位置的元素
set(int index,E e) 将index位置的元素更新为e
clear() 清空ArrayList
indexOf(Object o) 返回第一个的o的下标
lastIndexOf(Object o) 返回最后一个o的下标
subList(int fromIndex,int toIndex) 截取[fromIndex,toIndex)的元素
contains(Object o) 判断是否包含o


4. 自己实现ArrayList(Integer)

4.1 ArrayList构造

public class MyArrayList {
    int[] elem;//储存元素
    public int usedSize = 0;//元素个数,ArrayList集合大小默认为0
    private static final int DEFAULT_SIZE = 10;//ArrayList集合容量默认为10
    //构造方法
    public MyArrayList(){
        this.elem = new int[DEFAULT_SIZE];
    }
    ...
}


4.2 ArrayList容量的扩容

       当ArrayList中的元素个数不小于容量时,要对容量进行扩容,就是将ArrayList中的元素克隆到更大的数组中。

    private void ensureCapacity() {
        //将原数组克隆在更大的数组中
        elem = Arrays.copyOf(elem,2*elem.length);
    }


4.3 判断空满

       空:元素为0,即usedSize为0;

       满:元素个数等于容量

    //空
    private boolean isEmpty() {
        return usedSize == 0;
    }
    //满
    public boolean isFull() {
        return usedSize == this.elem.length;
    }


4.4 pos坐标是否合法(含有)

       即pos>=0 && pos < usedSize;

    //是否合法
    public boolean checkPosInAdd(int pos) {
        return pos >= 0 && pos < usedSize;//合法
    }


4.5 ArrayList的增删元素

       在尾插元素的时候,要判断是否具有足够的容量,如果不具有,要进行扩容,即调用4.2中ensureCapacity()方法。

在具体位置插入元素的时候,要判断坐标是否合法,不能大于数组大小,若大于,抛出异常。

       在删除元素的时候,要判断坐标是否合法,不能大于数组大小,若大于,抛出异常,也要判断是否存在这个元素,若不存在,返回 -1。

   // 新增元素,默认在数组最后新增
    public void add(int data) {
        if(isFull()){
            ensureCapacity();
        }
        this.elem[usedSize] = data;
        usedSize++;
    }
    // 在 pos 位置新增元素
    public void add(int pos, int data) {
        if(!checkPosInAdd(pos)){
            throw new ArrayIndexOutOfBoundsException("数组越界");
        }else{
            this.elem[pos] = data;
            usedSize++;
        }
    }
    //删除第一次遇到的key
    public void remove(int key) {
        if(isEmpty()){
            return;
        }
        int index = indexOf(key);
        if(index == -1){
            return;
        }
        for (int i = index; i < usedSize - 1; i++) {
            elem[i] = elem[i + 1];
        }
        usedSize--;
    }
    //删除index坐标的元素
    public void removeIndex(int index){
        if(!checkPosInAdd(index)){
            throw new ArrayIndexOutOfBoundsException("不合法");
        }else{
            for (int i = index; i < usedSize; i++) {
                elem[i] = elem[i + 1];
            }
            usedSize--;
        }
    }


4.6 包含元素

       即遍历整个数组,是否含有这个元素;

    // 判定是否包含某个元素
    public boolean contains(int toFind) {
        for (int i :
                this.elem) {
            if (i == toFind){
                return true;
            }
        }
        return false;
    }


4.7 get 和 set

       可以根据索引直接返回和更新值,但是需要注意合法;不合法,抛出异常;

    // 获取 pos 位置的元素
    public int get(int pos) {
        if(!checkPosInAdd(pos)){
            throw new ArrayIndexOutOfBoundsException("数组越界");
        }else{
            return elem[pos];
        }
    }
    // 给 pos 位置的元素设为【更新为】 value
    public void set(int pos, int value) {
        if(!checkPosInAdd(pos)){
            throw new ArrayIndexOutOfBoundsException("越界");
        }else {
            elem[usedSize] = value;
            usedSize++;
        }
    }


4.8 获得第一个元素坐标

       直接遍历数组,第一次碰到的这个元素,返回坐标,没有返回-1;

    // 查找某个元素对应的位置
    public int indexOf(int toFind) {
        for(int i = 0; i < usedSize; i++){
            if(elem[i] == toFind){
                return i;
            }
        }
        return -1;
    }


4.9 打印ArrayList

       可以直接遍历整个数组,进行打印;

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


4.10 清空ArrayList

       直接将usedSize大小变为0即可;

1. // 清空顺序表
2. public void clear() {
3.         usedSize = 0;
4.     }


目录
相关文章
HH
|
物联网
阿里云物联网平台基于MQTT.fx完成OTA升级
物联网平台提供OTA升级与管理服务。下面介绍OTA升级消息的Topic和Alink数据格式,包括设备上报OTA模块版本、物联网平台推送升级包信息、设备上报升级进度和设备请求获取最新升级包信息。
HH
4396 0
阿里云物联网平台基于MQTT.fx完成OTA升级
|
7月前
|
机器学习/深度学习 算法 关系型数据库
强化学习:动态规划求解最优状态价值函数——手把手教你入门强化学习(四)
本文介绍了基于模型的强化学习算法,重点讲解动态规划(DP)。动态规划通过分解问题为子问题求解状态价值函数,利用贝尔曼期望方程迭代更新。其核心性质包括最优子结构和重叠子问题,适用于已知转移概率和奖励的MDP场景。文章回顾了前期强化学习基础,并展望了后续内容如蒙特卡罗法。适合初学者系统了解强化学习算法原理与应用。
194 7
|
存储 C++
【PTA】L1-039 古风排版(C++)
【PTA】L1-039 古风排版(C++)
151 1
|
7月前
|
JSON API 开发者
1688店铺所有商品API接口(1688API系列)
1688店铺所有商品API接口允许开发者通过输入店铺ID,获取指定店铺内的全部商品信息,包括名称、价格、库存、图片和销售数据等。该接口支持排序和分页参数,返回JSON格式数据,便于解析和应用。Python示例展示了如何使用requests库发送GET请求并处理响应,助力电商数据分析与业务拓展。
|
9月前
|
存储 编译器 数据安全/隐私保护
【C++面向对象——类与对象】CPU类(头歌实践教学平台习题)【合集】
声明一个CPU类,包含等级(rank)、频率(frequency)、电压(voltage)等属性,以及两个公有成员函数run、stop。根据提示,在右侧编辑器补充代码,平台会对你编写的代码进行测试。​ 相关知识 类的声明和使用。 类的声明和对象的声明。 构造函数和析构函数的执行。 一、类的声明和使用 1.类的声明基础 在C++中,类是创建对象的蓝图。类的声明定义了类的成员,包括数据成员(变量)和成员函数(方法)。一个简单的类声明示例如下: classMyClass{ public: int
209 13
|
12月前
|
存储 监控 安全
服务器维护是确保服务器稳定运行、数据安全和性能优化的重要过程
【10月更文挑战第4天】服务器维护是确保服务器稳定运行、数据安全和性能优化的重要过程
305 65
|
数据采集 自然语言处理 Python
深入探索Python中的汉字处理技巧
深入探索Python中的汉字处理技巧
218 1
|
人工智能 搜索推荐 机器人
[AI Mem0] 概览,智能自我改进记忆层
[AI Mem0] 概览,智能自我改进记忆层
|
存储 关系型数据库 数据库
初探PostgreSQL体系结构
初探PostgreSQL体系结构
261 0
|
存储 算法 C++
C++一分钟之-容器概览:vector, list, deque
【6月更文挑战第21天】STL中的`vector`是动态数组,适合随机访问,但插入删除非末尾元素较慢;`list`是双向链表,插入删除快但随机访问效率低;`deque`结合两者优点,支持快速双端操作。选择容器要考虑操作频率、内存占用和性能需求。注意预分配容量以减少`vector`的内存重分配,使用迭代器而非索引操作`list`,并利用`deque`的两端优势。理解容器内部机制和应用场景是优化C++程序的关键。
263 5