数据结构*集合框架顺序表-ArrayList

news2025/4/21 20:46:37

集合框架

常见的集合框架
在这里插入图片描述
在这里插入图片描述

什么是顺序表

顺序表是一种线性表数据结构,它借助一组连续的存储单元来依次存储线性表中的数据元素。一般情况下采用数组存储。 在数组上完成数据的增删查改。

自定义简易版的顺序表

代码展示:

public interface IArrayList {
    //新增元素,默认在数组最后新增
    void add(int data);
    //在 pos 位置新增元素
    void add(int pos, int data);
    //判定是否包含某个元素
    boolean contains(int toFind);
    //查找某个元素对应的位置
    int indexOf(int toFind);
    //获取 pos 位置的元素
    int get(int pos);
    //给 pos 位置的元素设为 value
    void set(int pos, int value);
    //删除第⼀次出现的关键字key
    void remove(int toRemove);
    //获取顺序表⻓度
    int size();
    //清空顺序表
    void clear();
}
import java.util.Arrays;

public class MyArrayList implements IArrayList {
    private int useSize;
    private int[] elem;

    public MyArrayList() {
        this.elem = new int[Constant.DEFAULT_CAPACITY];
    }

    @Override//新增元素,默认在数组最后新增
    public void add(int data) {
        //1、是否能继续存放数据,不能就进行扩容
        if(isFill()) {
            grow();
        }
        //2、在数组末尾添加数据
        this.elem[useSize] = data;
        this.useSize++;
    }

    @Override//在 pos 位置新增元素
    public void add(int pos, int data) {
        //1、是不是满的
        if(isFill()) {
            grow();
        }
        //2、检查pos位置的合法性
        checkPosAdd(pos);
        //3、移动数据
        for (int i = useSize - 1; i >= pos ; i--) {
            elem[i+1] = elem[i];
        }
        /*if (useSize - pos >= 0) {
            System.arraycopy(elem, pos, elem, pos + 1, useSize - pos);
        }*/
        elem[pos] = data;
        useSize++;
    }
    private void checkPosAdd(int pos) {
        if(pos < 0 || pos > this.useSize) {
            throw new PosException(Constant.ADD_CHECK_MASSAGE);
        }
    }

    @Override//判定是否包含某个元素
    public boolean contains(int toFind) {
        for (int i = 0; i < this.useSize; i++) {
            if(elem[i] == toFind) {
                return true;
            }
        }
        return false;
    }

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

    @Override//获取 pos 位置的元素
    public int get(int pos) {
        //1、判断顺序表是否为空
        if(isEmpty()) {
            throw new isEmptyException(Constant.EMPTY_MASSAGE);
        }
        //2、判断pos位置是否合法
        checkPos(pos);

        return elem[pos];
    }
    private void checkPos(int pos) {
        if(pos < 0 || pos >= this.useSize) {
            throw new PosException(Constant.GET_CHECK_MASSAGE);
        }
    }
        @Override//给 pos 位置的元素设为 value
    public void set(int pos, int value) {
        if(isEmpty()) {
            throw new isEmptyException(Constant.EMPTY_MASSAGE);
        }
        checkPos(pos);
        elem[pos] = value;
    }

    @Override//删除第⼀次出现的关键字key
    public void remove(int toRemove) {
        if(isEmpty()) {
            throw new isEmptyException(Constant.EMPTY_MASSAGE);
        }
        int index = indexOf(toRemove);
        if(index == -1) {
            System.out.println("没有你要删除的数据");
            return;
        }
        for (int i = index; i < this.useSize - 1; i++) {
            elem[i] = elem[i+1];
        }
        elem[useSize - 1] = 0;
        useSize--;
    }

    @Override//获取顺序表⻓度
    public int size() {
        return this.useSize;
    }

    @Override//清空顺序表
    public void clear() {
        for (int i = 0; i < this.useSize; i++) {
            this.elem[i] = 0;
        }
        this.useSize = 0;
    }

    //是否为空
    private boolean isEmpty() {
        return useSize == 0;
    }
    //是否存满
    private boolean isFill() {
        return this.useSize == this.elem.length;//判断有效数据是否等于总数组长度
    }
    //数据扩容
    private void grow() {
        this.elem = Arrays.copyOf(this.elem,elem.length*2);
    }

    @Override
    public String toString() {
        return Arrays.toString(elem);
    }
}
public class PosException extends RuntimeException{
    public PosException() {
        super();
    }

    public PosException(String message) {
        super(message);
    }
}
public class isEmptyException extends RuntimeException{
    public isEmptyException() {
        super();
    }

    public isEmptyException(String message) {
        super(message);
    }
}
public class Constant {
    public static final int DEFAULT_CAPACITY = 5;
    public static final String EMPTY_MASSAGE = "顺序表为空";
    public static final String GET_CHECK_MASSAGE = "get方法的pos位置不合法";
    public static String ADD_CHECK_MASSAGE = "add方法的pos位置不合法";
}
public class Test {
    public static void main(String[] args) {
        MyArrayList myArrayList = new MyArrayList();
        myArrayList.add(1);
        myArrayList.add(2);
        myArrayList.add(3);
        myArrayList.add(4);
        myArrayList.add(2,10);
        myArrayList.add(2,10);
        System.out.println(myArrayList.contains(9));
        System.out.println(myArrayList.get(0));
        myArrayList.set(1,20);
        myArrayList.remove(10);
        System.out.println(myArrayList.size());
        System.out.println(myArrayList);
        myArrayList.clear();
        System.out.println(myArrayList);
    }
}

代码解释:

1、定义了一个IArrayList接口,里面有需要实现的方法。
2、Constant类用来存放一些常量。
3、自定义了一个MyArrayList顺序表。useSize表示数据中的有效长度,elem[]表示存储数据的数组。在构造方法中初始化了数组的默认大小。实现了如下方法:

方法功能
void add(int data)新增元素,默认在数组最后面新增
void add(int pos,int data)在pos位置新增元素
boolean contains(int toFind)判断是否包含某个元素
int indexOf(int toFind)查找某个元素对应的位置
int get(int pos)获得pos位置的元素
void set(int pos,int value)给pos位置的元素设为value
void remove(int toRemove)删除第一次出现的关键字toRemove
int size()获得顺序表长度
void clear()清空顺序表
4、两个自定义异常,分别表示数组中没有元素、pos位置不合法。
5、对于数据结构来说是很严谨的,需要考虑各种情况。将可能发生的情况进行书写。

官方定义的顺序表-ArrayList

类的属性

在这里插入图片描述

构造方法

有三种构造方法

无参构造方法

在这里插入图片描述

public static void test1() {
    ArrayList<Integer> arrayList = new ArrayList<>();
    arrayList.add(1);
    arrayList.add(2);
    arrayList.add("Hello");//报错
    System.out.println(arrayList);
    List<String> list = new ArrayList<>();//向上转型
    list.add("Hello");
    list.add("World");
    System.out.println(list);
}

此时new的是一个空的列表。arrayList已经限定为Integer类型,不能接收String类型。
对于add方法,查看源码:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
grow方法就是扩容操作,完成的是1.5倍扩容。

指定顺序表初始容量

在这里插入图片描述

public static void test2() {
    ArrayList<Integer> arrayList = new ArrayList<>(20);
    arrayList.add(10);
    arrayList.add(20);
    arrayList.add(30);
    System.out.println(arrayList);
}

利用其他Collection构建ArrayList

在这里插入图片描述

public static void test3() {
    ArrayList<Integer> arrayList = new ArrayList<>();
    arrayList.add(1);
    System.out.println(arrayList);
    ArrayList<Integer> arrayList1 = new ArrayList<>(arrayList);
    arrayList1.add(10);
    System.out.println(arrayList1);
    ArrayList<Number> arrayList2 = new ArrayList<>(arrayList);
    arrayList2.add(100);
    System.out.println(arrayList2);
    System.out.println(arrayList1);
    ArrayList<String> stringArrayList = new ArrayList<>(arrayList);//报错
}

输出:
[1]
[1, 10]
[1, 100]
[1, 10]

说明这种构造方法是创建一个新(单独)的列表,并继承传入的列表已有的值。

ArrayList常见操作

方法功能
boolean add(E e)尾插e
void add(int index,E element)将e插入到index位置
boolean addAll(Collection<? extends E> c)尾插c中的元素
E remove(int index)删除index位置元素
boolean remove(Object o)删除遇到的第一个o
E get(int index)获取下标index位置元素
E set(int index,E element)将下标index位置元素设置为element(替换)
void clear()清空
boolean contains(Object o)判断o是否在线性表中
int indexOf(Object o)返回第一个o所在下标
int lastindexOf(Object o)返回最后一个o所在下标
List<E> subList(int fromIndex,int toIndex)截取部分list

代码案例:

import java.util.ArrayList;
import java.util.List;

public class Test {
    public static void main(String[] args) {
        ArrayList<Integer> arrayList = new ArrayList<>();
        arrayList.add(1);
        arrayList.add(2);
        arrayList.add(3);
        arrayList.add(4);
        arrayList.add(4,10);
        System.out.println(arrayList);
        //arrayList.add(6,10);//报错,IndexOutOfBoundsException
        ArrayList<Integer> arrayList1 = new ArrayList<>();
        arrayList1.addAll(arrayList);
        System.out.println(arrayList1);
        arrayList1.add(5);
        System.out.println(arrayList);
        System.out.println("===========");
        arrayList.remove(4);
        System.out.println(arrayList);
        System.out.println("===========");
        Integer i = 4;
        arrayList.remove(i);
        System.out.println(arrayList);
        System.out.println("===========");
        System.out.println(arrayList.get(2));
        System.out.println("===========");
        arrayList.set(1,100);
        System.out.println(arrayList);
        System.out.println("===========");
        System.out.println(arrayList.contains(10));
        System.out.println("===========");
        ArrayList<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(2);
        list.add(3);
        list.add(4);
        list.add(5);
        list.add(6);
        list.add(7);
        list.add(8);
        list.add(9);
        list.add(10);
        System.out.println(list);//[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
        List<Integer> sublist = list.subList(2, 7);
        System.out.println(sublist);//[3, 4, 5, 6, 7]
        sublist.set(0,100);
        System.out.println(sublist);//[100, 4, 5, 6, 7]
        System.out.println(list);//[1, 2, 100, 4, 5, 6, 7, 8, 9, 10]
    }
}

代码解释:

需要注意的是:
1、subList()方法截取的范围是 [ fromeIndex,toIndex )
2、这里的截取并不是创建一个新的顺序表,而是获取原表上fromeIndex的地址。所以修改的是原表上的值。

ArrayList的遍历

代码案例:

public static void main(String[] args) {
    ArrayList<Integer> list = new ArrayList<>();
    list.add(1);
    list.add(2);
    list.add(3);
    list.add(4);
    list.add(5);
    list.add(6);
    list.add(7);
    System.out.println("--------for循环遍历--------");
    for(int i = 0; i < list.size();i++) {
        System.out.print(list.get(i)+" ");
    }
    System.out.println();
    System.out.println("--------foreach循环遍历--------");
    for (Integer integer : list) {
        System.out.print(integer + " ");
    }
    System.out.println();
    System.out.println("--------迭代器正序输出1--------");
    Iterator<Integer> it = list.listIterator();
    while (it.hasNext()) {
        System.out.print(it.next()+" ");
    }
    System.out.println();
    System.out.println("--------迭代器正序输出2--------");
    ListIterator<Integer> its = list.listIterator();
    while (its.hasNext()) {
        System.out.print(its.next()+" ");
    }
    System.out.println();
    System.out.println("--------迭代器正序输出3(从指定下标位置输出)--------");
    ListIterator<Integer> itss = list.listIterator(2);
    while (itss.hasNext()) {
        System.out.print(itss.next()+" ");
    }
    System.out.println();
    System.out.println("--------迭代器逆序输出--------");
    ListIterator<Integer> reits = list.listIterator(list.size());
    while (reits.hasPrevious()) {
        System.out.print(reits.previous()+" ");
    }
}

输出:
--------for循环遍历--------
1 2 3 4 5 6 7
--------foreach循环遍历--------
1 2 3 4 5 6 7
--------迭代器正序输出1--------
1 2 3 4 5 6 7
--------迭代器正序输出2--------
1 2 3 4 5 6 7
--------迭代器正序输出3从指定下标位置输出--------
3 4 5 6 7
--------迭代器逆序输出--------
7 6 5 4 3 2 1

代码解释:

1、list.listIterator() 是调用 list 对象的方法来获取一个列表迭代器。it.hasNext() 是判断迭代器 it 是否还有下一个元素。it.next() 方法会返回迭代器指向的下一个元素(即列表中的下一个 Integer 元素)。
2、实现了Iterator接口就能使用迭代器进行打印。
3、ListIterator接口继承了Iterator接口,也就是说有更多的方法。

嵌套列表

代码案例

1、

public static void test() {
    List<List<Integer>> list = new ArrayList<>();
    List<Integer> list0 = new ArrayList<>();
    list0.add(10);
    list0.add(100);
    list0.add(1000);
    List<Integer> list1 = new ArrayList<>();
    list1.add(20);
    list1.add(200);
    List<Integer> list2 = new ArrayList<>();
    list2.add(30);
    list2.add(300);
    List<Integer> list3 = new ArrayList<>();
    list3.add(40);
    list3.add(400);
    list3.add(4000);
    List<Integer> list4 = new ArrayList<>();
    list4.add(50);
    list4.add(500);
    list.add(list0);
    list.add(list1);
    list.add(list2);
    list.add(list3);
    list.add(list4);
    for(int i = 0; i < list.size();i++) {
        for (int j = 0; j < list.get(i).size(); j++) {
            System.out.print(list.get(i).get(j)+" ");
        }
        System.out.println();
    }
    System.out.println();
}

输出:
10 100 1000
20 200
30 300
40 400 4000
50 500

关系大致如图所示:
在这里插入图片描述
2、

public static List<List<Integer>> generate(int numRows) {
    List<List<Integer>> ret = new ArrayList<>();
    //定义起始行
    List<Integer> list0 = new ArrayList<>();
    list0.add(1);
    ret.add(list0);
    //定义后面的行
    for (int i = 1; i < numRows; i++) {
        //定义每行列表
        List<Integer> currentRow = new ArrayList<>();
        //第一个元素都是1
        currentRow.add(1);
        //中间操作
        List<Integer> preRow = ret.get(i - 1);
        for (int j = 1; j < i; j++) {
            //按照规律添加元素
            currentRow.add(preRow.get(j) + preRow.get(j-1));
        }
        //每行最后一个元素都是1
        currentRow.add(1);
        //currentRow行存储到ret中
        ret.add(currentRow);
    }
    return ret;
}

public static void main(String[] args) {
    List<List<Integer>> list = generate(5);
    for (List<Integer> integers : list) {
        for (Integer integer : integers) {
            System.out.print(integer + " ");
        }
        System.out.println();
    }
    System.out.println();
}

关系大致如图所示:
在这里插入图片描述

代码解释:

1、本质上是一个二维列表,可用于存储和操作二维数据结构。
2、代码二,实现的是杨辉三角的输出。

ArrayList顺序表的优缺点

优点

随机访问效率高,借助索引可以直接访问ArrayList里的任意元素,时间复杂度为O(1)。

缺点

1、扩容的时候可能会造成过多的内存消耗
2、插入和删除效率低,需要对元素进行插入与删除时,要移动后续的元素,时间复杂度为O(n)。

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

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

相关文章

VMware Workstation 保姆级 Linux(CentOS) 创建教程(附 iso)

文章目录 一、下载二、创建 一、下载 CentOS-7.9-x86_64-DVD-2009.iso 二、创建 VMware Workstation 保姆级安装教程(附安装包) VMware Workstation 保姆级安装教程(附安装包) VMware Workstation 保姆级安装教程(附安装包)

软考-信息系统项目管理师-2 信息技术发展

总结思维导图 云计算(掌握) (3)多租户和访问控制管理访问控制管理是云计算应用的核心问题之一云计算访问控制的研究主要集中在云计算访问控制模型、基于ABE密码体制的云计算访问控制、云中多租户及虚拟化访问控制研究云中多租户及虚拟化访问控制是云计算的典型特征。 大数据(…

Spring Boot JPA 开发之Not an entity血案

项目状况介绍 项目环境 JDK 21Spring Boot 3.4.3Hibernate: 6.6.13.Final项目描述 因为是微服务架构,项目层级如下 project-parent project-com project-A … project-X 其中: project-parent定义依赖库的版本project-com 定义了一些公用的方法和配置,包括持久层的配置。…

HTMLCSS实现轮播图效果

这段代码实现了一个具有自动轮播、手动切换功能的图片轮播图&#xff0c;并且配有指示器&#xff08;小圆点&#xff09;来显示当前图片位置。轮播图可通过左右箭头按钮进行手动切换&#xff0c;也能自动定时切换&#xff0c;当鼠标悬停在轮播图上时&#xff0c;自动轮播会暂停…

嵌入式学习——opencv图像库编程

环境配置 OpenCV&#xff08;Open Source Computer Vision Library&#xff09;是一个开源的计算机视觉和图像处理库&#xff0c;广泛用于各种计算机视觉任务&#xff0c;如图像处理、视频分析、人脸识别、物体检测、机器学习等。它提供了丰富的函数和工具&#xff0c;用于处理…

【每日八股】复习 MySQL Day1:事务

文章目录 复习 MySQL Day1&#xff1a;事务MySQL 事务的四大特性&#xff1f;并发事务会出现什么问题&#xff1f;MySQL 事务的隔离级别&#xff1f;不同事务隔离级别下会发生什么问题&#xff1f;MVCC 的实现原理&#xff1f;核心数据结构版本链构建示例可见性判断算法MVCC 可…

外接键盘与笔记本命令键键位不同解决方案(MacOS)

文章目录 修改键位第一步&#xff1a;打开设置第二步&#xff1a;进入键盘快捷键第三步&#xff1a;修改修饰键设置第四步&#xff1a;调整键位第五步&#xff1a;保存设置tips ikbc c87键盘win键盘没反应的解决亲测的方法这是百度的答案标题常规组合键尝试‌&#xff1a;型号差…

kotlin知识体系(五) :Android 协程全解析,从作用域到异常处理的全面指南

1. 什么是协程 协程(Coroutine)是轻量级的线程&#xff0c;支持挂起和恢复&#xff0c;从而避免阻塞线程。 2. 协程的优势 协程通过结构化并发和简洁的语法&#xff0c;显著提升了异步编程的效率与代码质量。 2.1 资源占用低&#xff08;一个线程可运行多个协程&#xff09;…

vscode stm32 variable uint32_t is not a type name 问题修复

问题 在使用vscodekeil开发stm32程序时&#xff0c;发现有时候vscode的自动补全功能失效&#xff0c;且problem窗口一直在报错。variable “uint32_t” is not a type name uint32_t 定义位置 uint32_t 实际是在D:/Keil_v5/ARM/ARMCC/include/stdint.h中定义的。将D:/Keil_v5…

Formality:Bug记录

相关阅读 Formalityhttps://blog.csdn.net/weixin_45791458/category_12841971.html?spm1001.2014.3001.5482 本文记录博主在使用Synopsys的形式验证工具Formality中遇到的一个Bug。 Bug复现 情况一 // 例1 module dff (input clk, input d_in, output d_out …

【java+Mysql】学生信息管理系统

学生信息管理系统是一种用于管理学生信息的软件系统&#xff0c;旨在提高学校管理效率和服务质量。本课程设计报告旨在介绍设计和实现学生信息管理系统的过程。报告首先分析了系统的需求&#xff0c;包括学生基本信息管理、成绩管理等功能。接着介绍了系统的设计方案&#xff0…

小白从0学习网站搭建的关键事项和避坑指南(2)

以下是针对小白从零学习网站搭建的 进阶注意事项和避坑指南&#xff08;第二期&#xff09;&#xff0c;覆盖开发中的高阶技巧、常见陷阱及解决方案&#xff0c;帮助你在实战中提升效率和质量&#xff1a; 一、进阶技术选型避坑 1. 前端框架选择 误区&#xff1a;盲目追求最新…

Windows 10 上安装 Spring Boot CLI详细步骤

在 Windows 10 上安装 Spring Boot CLI 可以通过以下几种方式完成。以下是详细的步骤说明&#xff1a; 1. 手动安装&#xff08;推荐&#xff09; 步骤 1&#xff1a;下载 Spring Boot CLI 访问 Spring Boot CLI 官方发布页面。下载最新版本的 .zip 文件&#xff08;例如 sp…

vue2技术练习-开发了一个宠物相关的前端静态商城网站-宠物商城网站

为了尽快学习掌握相关的前端技术&#xff0c;最近又实用 vue2做了一个宠物行业的前端静态网站商城。还是先给大家看一下相关的网站效果&#xff1a; 所以大家如果想快速的学习或者掌握一门编程语言&#xff0c;最好的方案就是通过学习了基础编程知识后&#xff0c;就开始利用…

嵌入式学习——远程终端登录和桌面访问

目录 通过桥接模式连接虚拟机和Windows系统 1、桥接模式 2、虚拟机和Windows连接&#xff08;1&#xff09; 3、虚拟机和Windows连接&#xff08;2&#xff09; 在Linux虚拟机中创建新用户 Windows系统环境下对Linux系统虚拟机操作 远程登录虚拟机&#xff08;1&#xff…

如何新建一个空分支(不继承 master 或任何提交)

一、需求分析&#xff1a; 在 Git 中&#xff0c;我们通常通过 git branch 来新建分支&#xff0c;这些分支默认都会继承当前所在分支的提交记录。但有时候我们希望新建一个“完全干净”的分支 —— 没有任何提交&#xff0c;不继承 master 或任何已有内容&#xff0c;这该怎么…

Qt编写推流程序/支持webrtc265/从此不用再转码/打开新世界的大门

一、前言 在推流领域&#xff0c;尤其是监控行业&#xff0c;现在主流设备基本上都是265格式的视频流&#xff0c;想要在网页上直接显示监控流&#xff0c;之前的方案是&#xff0c;要么转成hls&#xff0c;要么魔改支持265格式的flv&#xff0c;要么265转成264&#xff0c;如…

[第十六届蓝桥杯 JavaB 组] 真题 + 经验分享

A&#xff1a;逃离高塔(AC) 这题就是简单的签到题&#xff0c;按照题意枚举即可。需要注意的是不要忘记用long&#xff0c;用int的话会爆。 &#x1f4d6; 代码示例&#xff1a; import java.io.*; import java.util.*; public class Main {public static PrintWriter pr ne…

深⼊理解 JVM 执⾏引擎

深⼊理解 JVM 执⾏引擎 其中前端编译是在 JVM 虚拟机之外执⾏&#xff0c;所以与 JVM 虚拟机没有太⼤的关系。任何编程语⾔&#xff0c;只要能够编译出 满⾜ JVM 规范的 Class ⽂件&#xff0c;就可以提交到 JVM 虚拟机执⾏。⾄于编译的过程&#xff0c;如果你不是想要专⻔去研…

iwebsec靶场 文件包含关卡通关笔记11-ssh日志文件包含

目录 日志包含 1.构造恶意ssh登录命令 2.配置ssh日志开启 &#xff08;1&#xff09;配置sshd &#xff08;2&#xff09;配置rsyslog &#xff08;3&#xff09;重启服务 3.写入webshell木马 4.获取php信息渗透 5.蚁剑连接 日志包含 1.构造恶意ssh登录命令 ssh服务…