JavaDS —— 顺序表ArrayList

顺序表

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

模拟实现

下面是我们要自己模拟实现的方法:

在这里插入图片描述

首先我们要创建一个顺序表,顺序表包含一个数组,一个由于计数的计数器,还有一个默认的初始容量,我这里定义初始容量为5,比较好判断扩容是否成功。这里以整型数组为例:

    private int[] array;private int usedSize;//目前数据总数private static final int DEFAULT_CAPACITY = 5;//默认容量

默认构造方法

这里我们直接在构造方法里给数组进行初始化:

    public MyArrayList() {array = new int[DEFAULT_CAPACITY];}

尾插

尾插是指直接在所有数据的后面插入新数据,这里我们要注意数组容量是否已满,所以我们先写一个isFull方法判断数组是否容量已满:

    private boolean isFull() {if(usedSize == array.length) {return true;}return false;}

这个方法设置成private是因为这个方法只是给本类的方法提供的,不需要对外公开。


如果数组已满,那么我们就需要扩容,这里我扩容2倍:

    private void grow() {array = Arrays.copyOf(array,array.length * 2);}

现在来写尾插代码:

    public void add(int data) {//判满if(isFull()) {grow();}//插入数据array[usedSize++] = data;}

pos位置插入数据

首先我们要先检查pos位置是否合法,如果不合法的话就不用进行插入操作,直接抛出异常,我们先写异常代码:

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

检查pos位置是否合法:

    private void checkPosInAdd(int pos) throws PosException {if(pos < 0 || pos > usedSize) {throw new PosException("pos位置不合法");}}

现在写插入代码,首先判断pos是否合法,然后判断是否要扩容,最后我们进行插入操作即可,在插入代码中,我们使用try-catch来处理异常。

    public void add(int pos,int data) {try{checkPosInAdd(pos);//检查位置是否合法if(isFull()) {    //判满grow();}//移动数据for (int i = usedSize; i >= pos ; i--) {array[i+1] = array[i];}//插入数据array[pos] = data;usedSize++;}catch (PosException e) {System.out.println("pos位置不合法!");e.printStackTrace();}}

contains

是否包含某个元素,使用布尔值进行返回,这里直接遍历数组查找即可。

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

indexOf

查找某个元素的下标,找到则返回该元素的下标,没有找到则返回 -1

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

get

找到pos位置的元素,这里要注意先判断pos是否合法,但是这里的检查pos和上面我们写过的checkPosInAdd是不一样的,这里的pos必须是有元素的下标范围,也就是不包含usedSize这个下标,因为这个是没有有效数据的,是待插入的空位,所以我们要再写一个检查pos方法:

    private void checkPosInFind(int pos) throws PosException {if(pos < 0 || pos >= usedSize) {throw new PosException("pos位置不合法");}}

    public int get(int pos) {try{checkPosInFind(pos);return array[pos];}catch (PosException e) {System.out.println("pos位置不合法!");e.printStackTrace();}return -1;}

set

更新pos位置的数据,还是要判断pos位置是否合法,这里使用发判断方法应该为checkPosInFind

    public void set(int pos, int data) {try{checkPosInFind(pos);array[pos] = data;}catch (PosException e) {System.out.println("pos位置不合法!");e.printStackTrace();}}

remove

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

    public void remove(int key) {for (int i = 0; i < usedSize; i++) {if(array[i] == key) {for (int j = i; j < usedSize - 1; j++) {array[j] = array[j+1];}usedSize--;return;}}}

size

获取顺序表的长度,这里直接返回usedSize即可

    public int size() {return usedSize;}

display

打印顺序表,该方法是便于测试,真正的顺序表并没有这个方法

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

clear

清空顺序表,直接将usedSize赋值为0即可,下次使用的时候,会直接覆盖之前的数据的。

    public void clear() {usedSize = 0;}

完整代码

import java.util.Arrays;public class MyArrayList {private int[] array;private int usedSize;//目前数据总数private static final int DEFAULT_CAPACITY = 5;//默认容量public MyArrayList() {array = new int[DEFAULT_CAPACITY];}/*判满,满则返回true,否则返回false*/private boolean isFull() {if(usedSize == array.length) {return true;}return false;}//扩容 2倍扩容private void grow() {array = Arrays.copyOf(array,array.length * 2);}//尾插public void add(int data) {//判满if(isFull()) {grow();}//插入数据array[usedSize++] = data;}//判断pos是否合法/*不合法则抛出异常增加方法*/private void checkPosInAdd(int pos) throws PosException {if(pos < 0 || pos > usedSize) {throw new PosException("pos位置不合法");}}//指定pos位置插入数据public void add(int pos,int data) {try{checkPosInAdd(pos);//检查位置是否合法if(isFull()) {    //判满grow();}//移动数据for (int i = usedSize; i >= pos ; i--) {array[i+1] = array[i];}//插入数据array[pos] = data;usedSize++;}catch (PosException e) {System.out.println("pos位置不合法!");e.printStackTrace();}}//是否包含某个元素public boolean contains(int toFind) {for (int i = 0; i < usedSize; i++) {if(array[i] == toFind){return true;}}return false;}//查找某个元素的下标public int indexOf(int toFind) {for (int i = 0; i < usedSize; i++) {if(array[i] == toFind) {return i;}}return -1;}//判断pos是否合法/*查找方法不合法则抛出异常*/private void checkPosInFind(int pos) throws PosException {if(pos < 0 || pos >= usedSize) {throw new PosException("pos位置不合法");}}//获取pos位置的元素public int get(int pos) {try{checkPosInFind(pos);return array[pos];}catch (PosException e) {System.out.println("pos位置不合法!");e.printStackTrace();}return -1;}//更新pos位置的数据public void set(int pos, int data) {try{checkPosInFind(pos);array[pos] = data;}catch (PosException e) {System.out.println("pos位置不合法!");e.printStackTrace();}}//删除第一次出现的关键字keypublic void remove(int key) {for (int i = 0; i < usedSize; i++) {if(array[i] == key) {for (int j = i; j < usedSize - 1; j++) {array[j] = array[j+1];}usedSize--;return;}}}//获取顺序表的长度public int size() {return usedSize;}//打印顺序表,该方法是便于测试,真正的顺序表并没有这个方法public void display() {for (int i = 0; i < usedSize; i++) {System.out.print(array[i] + " ");}System.out.println();}//清空顺序表public void clear() {usedSize = 0;}
}

ArrayList 的使用

Java已经封装好顺序表供我们使用,就是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 的下标

更多详细的方法可自行查阅官方文档

上面很多方法是我们自己模拟实现过的,这里就不一一举例演示。

ArrayList 的成员方法

在这里插入图片描述

ArrayList 构造方法

一共提供了三个构造方法:

方法解释
ArrayList()无参构造
ArrayList(Collection<? extends E> c)利用其他 Colletion 构建 ArrayList
ArrayList(int initialCapacity)指定顺序表初始容量

ArrayList(int initialCapacity)指定顺序表初始容量看一下源码还是很好理解的,初始容量大于零就开辟一块连续的空间,等于零就给一个空数组,小于零则抛出异常。

在这里插入图片描述

首先要知道下面的关系图:
在这里插入图片描述

从上图我们可以得知ArrayList是包含Collection这个接口的,所以可以接收Colletion的参数,Colletion后面的<? extends E> 中的 ? 是通配符,后面的文章会提到。

在这里插入图片描述


我们重点是看无参的构造方法:

在这里插入图片描述

直接赋值一个空数组,大家来看一下下面的代码,明明是空数组,但是为什么可以直接add而不会报错呢?

    public static void main(String[] args) {ArrayList<Integer> list = new ArrayList<>();list.add(10);list.add(20);System.out.println(list);}

在这里插入图片描述

我们点过去看看源码是什么:

在这里插入图片描述

在这里插入图片描述

到了这里大家应该明白了,在使用add的时候,我们看到源码里写了当 s == 数组长度的时候,Java底层会帮我们自动扩容。

ArrayList 实例化

我们经常使用List或者ArrayList来接收顺序表实例化的对象.

        List<Integer> list = new ArrayList<>();ArrayList<Integer> list2 = new ArrayList<>();

由于List是ArrayList的接口,所以可以接收,但是注意List是接口意味着不能进行实例化,使用List接收的参数只能使用List有点方法,由于ArrayList有很多接口,一定是拓展了很多东西的,如果List接口没有包含的方法,使用List接收的参数不能调用其他方法,但是使用ArrayList接收的话,所有ArrayList实现的方法都是可以调用的,只要是公开访问即可.

ArrayList 遍历方法

ArrayList 可以使用三方方式遍历:for循环+下标、foreach、使用迭代器,还可以直接打印里面的内容。

        int size = list.size();for (int i = 0; i < size; i++) {System.out.print(list.get(i) + " ");}System.out.println();

无论是Integer还是int接收元素,Java底层会帮我们自动拆箱的.

        for (int x: list) {System.out.print(x + " ");}System.out.println();for (Integer y: list) {System.out.print(y + " ");}System.out.println();
        ListIterator<Integer> it =  list.listIterator(list.size());while (it.hasPrevious()) {System.out.print(it.previous()+" ");}System.out.println();

Java的ArrayList的父类是重写过toString方法的.

        System.out.println(list);

在这里插入图片描述

实践

杨辉三角

在这里插入图片描述

在这里插入图片描述

这里要注意 List<List< Integer>> ,这个意思表示外面的list的元素是list,里面的list的元素是Integer,例如下图所示:类似二维数组~

在这里插入图片描述

代码:

class Solution {public List<List<Integer>> generate(int numRows) {List<List<Integer>> list = new ArrayList<>();List<Integer> list0 = new ArrayList<>();list0.add(1);list.add(list0);for(int i=1;i<numRows;i++) {List<Integer> list1 = new ArrayList<>();for(int j=0;j<=i;j++) {if(j==0 || j==i) {list1.add(1);} else {list1.add(list.get(i-1).get(j-1) + list.get(i-1).get(j));}}list.add(list1);}return list;}
}

洗牌功能实现

public class Card {private int number;private String cardColor;public Card(int number, String cardColor) {this.number = number;this.cardColor = cardColor;}@Overridepublic String toString() {return "Card{" +cardColor + '\'' +number +'}';}
}
import java.util.ArrayList;
import java.util.List;
import java.util.Random;public class PlayCard {private static final String[] cardColor = {"♦","♣","♥","♠"};//购买52张牌public List<Card> buyCards() {List<Card> list = new ArrayList<>();for (int i = 1; i <= 13; i++) {for (int j = 0; j < 4; j++) {Card card = new Card(i,cardColor[j]);list.add(card);}}return list;}//洗牌public void shuffle(List<Card> list) {Random random = new Random();int size = list.size();for (int i = 0; i < size; i++) {int index = random.nextInt(size);//生成 0 ~ i-1 的随机数Card card = list.get(index);list.set(index,list.get(i));list.set(i,card);}}//发牌public List<List<Card>> deal(List<Card> cards) {List<List<Card>> list = new ArrayList<>();//创建三个人List<Card> list0 = new ArrayList<>();List<Card> list1 = new ArrayList<>();List<Card> list2 = new ArrayList<>();list.add(list0);list.add(list1);list.add(list2);int size = cards.size();int size2 = list.size();int count = 0;boolean flag = true;while(flag) {for (int j = 0; j < size2; j++) {list.get(j).add(cards.remove(0));count++;if(count == size){flag = false;break;}}}return list;}
}

这里要注意随机数的建立,首先先实例化Ramdom对象,然后使用nextInt方法,nextInt(int bound),生成的随机数范围是0~bound-1.

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

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

相关文章

关于Mars3d的入门

关于Mars3d的入门 一. 创建地球&#xff0c;加载瓦片图层二 矢量图层2.1 常用矢量图层2.1.1 GraphicLayer2.1.2 GeoJsonLayer 2.2 矢量图层的点击事件 三 矢量数据四 事件机制 一. 创建地球&#xff0c;加载瓦片图层 // 1. 创建地球let map new mars3d.Map("mars3dContai…

从零开始做题:My_lllp

题目 给出一张png图片 解题 ┌──(holyeyes㉿kali2023)-[~/Misc/题目/zulu/My_lllp] └─$ python2 lsb.py extract my_lllp.png out.txt my_lllp [] Image size: 1080x1079 pixels. [] Written extracted data to out.txt. ┌──(holyeyes㉿kali2023)-[~/Misc/题目/zul…

简易Qt串口助手

界面显示如下 关于串口类 初始化 设置串口号 设置波特率 打开串口 发送按钮功能实现 接收数据显示在控件中 关闭串口

使用 MFA 保护对企业应用程序的访问

多因素身份验证&#xff08;MFA&#xff09;是在授予用户访问特定资源的权限之前&#xff0c;使用多重身份验证来验证用户身份的过程&#xff0c;仅使用单一因素&#xff08;传统上是用户名和密码&#xff09;来保护资源&#xff0c;使它们容易受到破坏&#xff0c;添加其他身份…

springboot非物质文化遗产管理系统-计算机毕业设计源码16087

目录 摘要 1 绪论 1.1 选题背景与意义 1.2国内外研究现状 1.3论文结构与章节安排 2系统分析 2.1 可行性分析 2.2 系统流程分析 2.2.1系统开发流程 2.2.2 用户登录流程 2.2.3 系统操作流程 2.2.4 添加信息流程 2.2.5 修改信息流程 2.2.6 删除信息流程 2.3 系统功能…

前端开发过程中经常遇到的问题以及对应解决方法 (持续更新)

我的朋友已经工作了 3 年&#xff0c;他过去一直担任前端工程师。 不幸的是&#xff0c;他被老板批评了&#xff0c;因为他在工作中犯了一个错误&#xff0c;这是一个非常简单但容易忽视的问题&#xff0c;我想也是很多朋友容易忽视的一个问题。 今天我把它分享出来&#xff…

Linux三剑客(grep、awk和sed)操作及与管道结合使用

1. 总览 grep、sed和awk被称为Linux三剑客&#xff0c;是因为它们在文本处理和数据操作方面极其强大且常用。 Linux三剑客在文件处理中的作用&#xff1a; grep&#xff08;数据查找定位&#xff09;&#xff1a;文本搜索工具&#xff0c;在文件中搜索符合正则表达式的文本内容…

Redis原理-数据结构

Redis原理篇 1、原理篇-Redis数据结构 1.1 Redis数据结构-动态字符串 我们都知道Redis中保存的Key是字符串&#xff0c;value往往是字符串或者字符串的集合。可见字符串是Redis中最常用的一种数据结构。 不过Redis没有直接使用C语言中的字符串&#xff0c;因为C语言字符串存…

【大模型LLM面试合集】大语言模型架构_attention

1.attention 1.Attention 1.1 讲讲对Attention的理解&#xff1f; Attention机制是一种在处理时序相关问题的时候常用的技术&#xff0c;主要用于处理序列数据。 核心思想是在处理序列数据时&#xff0c;网络应该更关注输入中的重要部分&#xff0c;而忽略不重要的部分&…

BJT的结构(晶体管电压/电流+β+晶体管特性曲线/截止与饱和+直流负载线(Q点))+单片机数码管基础

2024-7-8&#xff0c;星期一&#xff0c;20:23&#xff0c;天气&#xff1a;晴&#xff0c;心情&#xff1a;晴。今天没有什么特殊的事情发生&#xff0c;周末休息了两天&#xff0c;周一回来继续学习啦&#xff0c;加油加油&#xff01;&#xff01;&#xff01; 今日完成模电…

视频号矩阵管理系统:短视频内容营销的智能助手

随着短视频行业的蓬勃发展&#xff0c;视频号矩阵管理系统应运而生&#xff0c;为内容创作者和品牌提供了一站式的短视频管理和营销解决方案。本文将深入探讨视频号矩阵管理系统的核心功能&#xff0c;以及它如何助力用户在短视频营销领域取得成功。 视频号矩阵管理系统概述 …

在PyTorch中使用TensorBoard

文章目录 在PyTorch中使用TensorBoard1.安装2.TensorBoard使用2.1创建SummaryWriter实例2.2利用add_scalar()记录metrics2.3关闭Writer2.4启动TensorBoard 3.本地连接服务器使用TensorBoard3.1方法一&#xff1a;使用SSH命令进行本地端口转发3.2方法二&#xff1a;启动TensorBo…

如何将资源前端通过 Docker 部署到远程服务器

作为一个程序员&#xff0c;在开发过程中&#xff0c;经常会遇到项目部署的问题&#xff0c;在现在本就不稳定的大环境下&#xff0c;前端开发也需要掌握部署技能&#xff0c;来提高自己的生存力&#xff0c;今天就详细说一下如何把一个前端资源放到远程服务器上面通过docker部…

【Python】不小心卸载pip后(手动安装pip的两种方式)

文章目录 方法一&#xff1a;使用get-pip.py脚本方法二&#xff1a;使用easy_install注意事项 不小心卸载pip后&#xff1a;手动安装pip的两种方式 在使用Python进行开发时&#xff0c;pip作为Python的包管理工具&#xff0c;是我们安装和管理Python库的重要工具。然而&#x…

产品经理技能揭秘:如何巧妙启发需求,引领市场新潮流

文章目录 引言一、需求启发的定义二、需求启发的艺术三、需求启发的重要性四、需求启发的流程五、需求启发的问题与挑战内部自身的问题与挑战&#xff1a;挑战一&#xff1a;知识的诅咒挑战二&#xff1a;做与定义的不同挑战三&#xff1a;沟通障碍挑战四&#xff1a;需求变更频…

solidity:构造函数和修饰器、事件

构造函数​ 构造函数&#xff08;constructor&#xff09;是一种特殊的函数&#xff0c;每个合约可以定义一个&#xff0c;并在部署合约的时候自动运行一次。它可以用来初始化合约的一些参数&#xff0c;例如初始化合约的owner地址&#xff1a; address owner; // 定义owner变…

电脑找回彻底删除文件?四个实测效果的方法【一键找回】

电脑数据删除了还能恢复吗&#xff1f;可以的&#xff0c;只要我们及时撤销上一步删除操作&#xff0c;还是有几率找回彻底删除文件。 当我们的电脑文件被彻底删除后&#xff0c;尽管恢复的成功率可能受到多种因素的影响&#xff0c;但仍有几种方法可以尝试找回这些文件。本文整…

使用 docker buildx 构建跨平台镜像

buildx是Docker官方提供的一个构建工具&#xff0c;它可以帮助用户快速、高效地构建Docker镜像&#xff0c;并支持多种平台的构建。使用buildx&#xff0c;用户可以在单个命令中构建多种架构的镜像&#xff0c;例如x86和arm架构&#xff0c;而无需手工操作多个构建命令。此外bu…

【React Hooks原理 - useCallback、useMemo】

介绍 在实际项目中&#xff0c;useCallback、useMemo这两个Hooks想必会很常见&#xff0c;可能我们会处于性能考虑避免组件重复刷新而使用类似useCallback、useMemo来进行缓存。接下来我们会从源码和使用的角度来聊聊这两个hooks。【源码地址】 为什么要有这两个Hooks 在开始…

使用selenium定位input标签下的下拉框

先来看一下页面效果&#xff1a;是一个可输入的下拉列表 再来看一下下拉框的实现方式&#xff1a; 是用<ul>和<li>方式来实现的下拉框&#xff0c;不是select类型的&#xff0c;所以不能用传统的select定位方法。 在着手定位元素前一定一定要先弄清楚下拉列表…