Java——ArrayList与顺序表

一、线性表

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

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

二、顺序表

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

自己实现顺序表,帮助理解ArrayList中方法的底层原理

框架代码:

public interface IList {// 新增元素,默认在数组最后新增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 位置的元素设为 valuevoid set(int pos, int value);//删除第一次出现的关键字keyvoid remove(int toRemove);// 获取顺序表长度int size();// 清空顺序表void clear();// 打印顺序表,注意:该方法并不是顺序表中的方法,为了方便看测试结果给出的void display();//判满boolean isFull();
}public class MyArrayList implements IList{public int[] elem;public int usedSize;public MyArrayList() {this.elem = new int[10];}@Overridepublic void add(int data) {}@Overridepublic boolean isFull() {}@Overridepublic void add(int pos, int data) {}@Overridepublic boolean contains(int toFind) {return false;}@Overridepublic int indexOf(int toFind) {return 0;}@Overridepublic int get(int pos) {return 0;}@Overridepublic void set(int pos, int value) {}@Overridepublic void remove(int toRemove) {}@Overridepublic int size() {return 0;}@Overridepublic void clear() {}@Overridepublic void display() {}
}public class Test {public static void main(String[] args) {//两种创建对象的方式IList iList = new MyArrayList();MyArrayList myArrayList = new MyArrayList();}
}

add(int data)方法: 

add(int data,int pos)方法:

定义一个异常类,用来判断pos位置是否合法

public class PosNotLegalException extends RuntimeException {public PosNotLegalException() {}public PosNotLegalException(String msg) {super(msg);}
}

private 修饰的 checkPosOfAdd() 函数,检测pos,若不合法则抛出异常

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

从最后一个元素位置开始,将pos之后的元素往后移一位,再将data插入到pos位置,最后usedSize++

    @Overridepublic void add(int pos, int data) {//判断位置是否合法try {checkPosOfAdd(pos);}catch(PosNotLegalException e) {e.printStackTrace();}//判满if(isFull()) {this.elem = Arrays.copyOf(elem,2*elem.length);}for (int i = this.usedSize-1; i >= pos; i--) {this.elem[i+1] = this.elem[i];}this.elem[pos] = data;this.usedSize++;}

判断是否包含某个元素contains方法

    @Overridepublic boolean contains(int toFind) {for (int i = 0; i < usedSize; i++) {if(this.elem[i] == toFind) {return true;}}return false;}

返回查找元素下标indexOf方法

    @Overridepublic int indexOf(int toFind) {for (int i = 0; i < usedSize; i++) {if(this.elem[i] == toFind) {return i;}}return -1;}

获取pos下标位置元素get方法

    @Overridepublic int get(int pos) {try {checkPosOfAddGetAndSet(pos);//判断pos位置是否合法,此处pos不能等于usedSize,和判满异常区分}catch(PosNotLegalException e) {e.printStackTrace();}return elem[pos];}private void checkPosOfAddGetAndSet(int pos) throws PosNotLegalException{if(pos < 0 || pos >= usedSize) {throw new PosNotLegalException("get or set 中pos位置不合法!");}}

设置pos下标位置的值为value的set方法(相当于更新元素)

    @Overridepublic void set(int pos, int value) {try {checkPosOfAddGetAndSet(pos);}catch(PosNotLegalException e) {e.printStackTrace();}elem[pos] = value;}

删除第一次出现的元素,remove方法

    @Overridepublic void remove(int toRemove) {int pos = indexOf(toRemove);//判断该元素是否存在if(pos == -1) {System.out.println("没有要删除的数字!");return;}for (int i = pos; i < usedSize-1; i++) {//将后续元素前移覆盖即可elem[i] = elem[i+1];}this.usedSize--;}

删除所有出现的toRemove元素,removeAll方法

    public void removeAll(int toRemove) {int pos = indexOf(toRemove);if(pos == -1) {System.out.println("没有要删除的数字!");return;}int i = 0;while(i < usedSize) {if(elem[i] == toRemove) {for(int j = i; j < usedSize-1; j++) {elem[j] = elem[j+1];}this.usedSize--;}if(elem[i] != toRemove) {i++;}}}

获取顺序表长度,清空顺序表,打印顺序表

    @Overridepublic int size() {return usedSize;}@Overridepublic void clear() {/*若顺序表元素为引用类型,需回收内存for (int i = 0; i < usedSize; i++) {elem[i] = null;}*/usedSize = 0;}@Overridepublic void display() {for (int i = 0; i < usedSize; i++) {System.out.print(elem[i] + " ");}System.out.println();}

三、ArrayList的使用

我们查看ArratList的源码

发现其是一个泛型类,创建其对象的两种方法如下:

    public static void main(String[] args) {ArrayList<Integer> arrayList = new ArrayList<>();List<Integer> list = new ArrayList<>();//推荐这种}

区别:

3.1 ArrayList的构造

我们查看ArrayList的源码,发现其有三个构造方法:

第一个无参构造方法:

查看源码:

虽然没有给数组分配大小,但是当我们add元素时,却依然能成功:

这是因为:当调用不带参数的构造方法进行add时,会分配大小为10的内存,当内存占满了,会进行1.5倍扩容


第二种,有一个整型参数的构造方法


第三种: 

3.2 ArrayList的常见方法

1. boolean addAll(Collection c) 尾插 c 中的元素

    public static void main(String[] args) {List<Integer> list = new ArrayList<>();list.add(10);list.add(12);//自动装箱,int类型变为Integer类型System.out.println(list);List<Integer> list1 = new ArrayList<>(list);System.out.println(list1);}

运行结果:

 

 2. E remove(int index) 删除 index 位置元素

报错为数组越界异常,remove不会进行装箱操作

若想直接输入删除的元素:

    public static void main(String[] args) {List<Integer> list = new ArrayList<>();list.add(10);list.add(12);System.out.println(list);//list.remove(1);//删除1下标,没问题//System.out.println(list);//list.remove(12);//想删除12这个元素,会报错list.remove(Integer.valueOf(12));//将int类型的12,转为Integer类型对象,remove删除值为12的对象}

3. List subList(int fromIndex, int toIndex) 截取部分 list

3.3 Arrays的遍历

ArrayList 可以使用三方方式遍历:for循环+下标、foreach、使用迭代器

    public static void main(String[] args) {List<Integer> list = new ArrayList<>();list.add(10);list.add(11);list.add(12);list.add(13);//第一种打印方式:System.out.println(list);//该方法或其父类中肯定重写了toString方法System.out.println("===fori===");//第二种for循环for (int i = 0; i < list.size(); i++) {System.out.print(list.get(i) + " ");}System.out.println();System.out.println("===foreach===");//第三种foreach循环for(Integer x : list) {System.out.print(x + " ");}System.out.println();System.out.println("===iterator打印===");//第四种 iterator打印Iterator<Integer> it = list.iterator();while(it.hasNext()) {//当it后面还有元素就进入循环System.out.print(it.next() + " ");}System.out.println();System.out.println("===ListIterator,专门打印List===");//第五种 ListIterator,专门打印ListListIterator<Integer> it2 = list.listIterator();while(it2.hasNext()) {System.out.print(it2.next() + " ");}System.out.println();System.out.println("===ListIterator 倒着打印===");//第六种 ListIterator 倒着打印ListIterator<Integer> it3 = list.listIterator(list.size());while(it3.hasPrevious()) {System.out.print(it3.previous() + " ");}}

运行结果:

四、ArrayList具体使用

4.1 简单的洗牌算法

需求:生成52张牌,没有大小王,四种花色("♠", "♥", "♣", "♦"),每种13张,乱序洗牌,3个人轮流抓牌,每人抓5张,最后打印每个人手中牌及剩下的牌

框架:

Card类,声明牌的属性,牌的构造方法,重写toString

public class Card {public int rank;//数字public String suit;//花色public Card(int rank,String suit) {this.rank = rank;this.suit = suit;}@Overridepublic String toString() {return "{" + suit + " " + rank + "}";}
}

Cards类,生成52张牌的方法buyCard

import java.util.ArrayList;
import java.util.List;public class Cards {public static final String[] suits = {"♠", "♥", "♣", "♦"};//4个花色 每种13张public List<Card> buyCard() {List<Card> cardList = new ArrayList<>();//创建泛型类型为Card的顺序表for (int i = 0; i < 4; i++) {//四种花色循环for (int j = 1; j <= 13; j++) {//生成每种花色的1~13数字牌int rank = j;String suit = suits[i];Card card = new Card(rank,suit);//构造牌对象cardList.add(card);//将牌对象添加到顺序表中}}return cardList;}
}

Test类

import java.util.List;public class Test {public static void main(String[] args) {Cards cards = new Cards();//创建牌对象List<Card> cardList = cards.buyCard();//buyCard()返回值类型为List<Card>System.out.println(cardList);}
}

洗牌操作

//Cards类public void shuffle(List<Card> cardList) {Random random = new Random();for (int i = cardList.size()-1; i > 0; i--) {//从后向前循环int randIndex = random.nextInt(i);//生成随机整数,该整数范围:0~i之间swap(cardList,i,randIndex);//交换i下标与生成随机整数下标处的值}}//根据生成随机整数来打乱牌序private void swap(List<Card> cardList,int i,int j) {Card tmp = cardList.get(i);cardList.set(i,cardList.get(j));cardList.set(j,tmp);}

3个人轮流抓牌,每人抓5张

    public void drawCard(List<Card> cardList) {List<Card> hand1 = new ArrayList<>();//三个手对象,用来存放每个人每次摸的牌List<Card> hand2 = new ArrayList<>();List<Card> hand3 = new ArrayList<>();List<List<Card>> hands = new ArrayList<>();//创建一个泛型类为List<Card>的对象,用来存放三个人hands.add(hand1);//将三个人放到hans的顺序表中hands.add(hand2);hands.add(hand3);for (int i = 0; i < 5; i++) {//外循环5次,模拟摸5次牌,for (int j = 0; j < 3; j++) {//内循环3次,模拟三个人Card card = cardList.remove(0);//创建Card类型对象,暂存摸出的牌hands.get(j).add(card);//将牌放到相应人的相应手里面}}System.out.println("第一个人的牌" + hand1);System.out.println("第二个人的牌" + hand2);System.out.println("第三个人的牌" + hand3);}

扩展:给摸完牌后的牌排序

4.2 杨辉三角

    //杨辉三角public List<List<Integer>> generate(int numRows) {List<List<Integer>> ret = new ArrayList<>();List<Integer> list = new ArrayList<>();list.add(1);ret.add(list);for (int i = 1; i < numRows; i++) {List<Integer> curRow = new ArrayList<>();curRow.add(1);for(int j = 1; j < i; j++) {List<Integer> preRow = ret.get(i-1);int x = preRow.get(j);int y = preRow.get(j-1);curRow.add(x+y);}curRow.add(1);ret.add(curRow);}return ret;}

4.3 面试题:将str1中出现的str2中的相同元素删除

例:

str1:welcome to china

str2:come

要求输出结果:wl t hina

两种解决方式:

    //ArrayList实现public static void func2(String str1,String str2) {List<Character> list = new ArrayList<>();//用ArrayList实现该方法,最好使用接口进行对象创建for (int i = 0; i < str1.length(); i++) {char ch = str1.charAt(i);//str2是字符串,ch是字符,为了解决他们用contains方法会报错的问题//if(!str2.contains(ch)) {//将该行代码改为以下,在ch后面+""即可变为String类型if(!str2.contains(ch+"")) {list.add(ch);}}for(char ch : list) {System.out.print(ch);}System.out.println();}//StringBuilder实现public static void func(String str1,String str2) {StringBuilder stringBuilder = new StringBuilder();for (int i = 0; i < str1.length(); i++) {char ch = str1.charAt(i);if(!str2.contains(ch+"")) {stringBuilder.append(ch);}}System.out.println(stringBuilder);}

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

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

相关文章

Qt无边框

最简单的可拖动对话框(大小不可改变) #ifndef DIALOG_H #define DIALOG_H/*** file dialog.h* author lpl* brief 无边框dialog类* date 2024/06/05*/ #include <QDialog> #include <QMouseEvent> namespace Ui { class Dialog; } /*** brief The Dialog class* 无…

java版知识付费saas租户平台:剖析现代知识付费平台的功能架构与运营逻辑

在数字化学习的时代背景下&#xff0c;知识付费平台已经成为教育行业的一颗璀璨明星&#xff0c;以其用户需求为中心&#xff0c;提供便捷高效的学习途径。这些平台汇聚了众多专业知识&#xff0c;覆盖职业技能、生活兴趣和人文社科等多个领域&#xff0c;满足不同用户的学习需…

基于Python的AI动物识别技术研究

基于Python的AI动物识别技术研究 开发语言:Python 数据库&#xff1a;MySQL所用到的知识&#xff1a;Django框架工具&#xff1a;pycharm、Navicat、Maven 系统功能实现 系统的登录模块设计 本次设计的AI动物识别系统为了保证用户的数据安全&#xff0c;设计了登录的模块&…

网络基础-IP协议

文章目录 前言一、IP报文二、IP报文分片重组IP分片IP分片示例MTUping 命令可以验证MTU大小Windows系统&#xff1a;Linux系统: 前言 基础不牢&#xff0c;地动山摇&#xff0c;本节我们详细介绍IP协议的内容。 一、IP报文 第一行&#xff1a; 4位版本号指定IP协议的版本&#…

C++使用thread_local实现每个线程下的单例

对于一个类&#xff0c;想要在每个线程种有且只有一个实例对象&#xff0c;且线程之间不共享该实例&#xff0c;可以按照单例模式的写法&#xff0c;同时使用C11提供的thread_local关键字实现。 在单例模式的基础上&#xff0c;使用thread_local关键字修饰单例的instance&…

NineData云原生智能数据管理平台新功能发布|2024年5月版

重点发布​ 数据库 DevOps - 表分组查询​ 在企业用户规模达到一定程度后&#xff0c;分库分表成为一种常见的数据库架构选择。在这种情况下&#xff0c;查询和维护数据需要高效的解决方案&#xff0c;以避免手动逐一查询、变更和汇总多个分库和分表的繁琐操作。 库分组变更…

LLM中完全消除矩阵乘法,效果惊人!10亿参数在FPGA上运行功耗接近大脑!!

一直以来&#xff0c;矩阵乘法&#xff08;MatMul&#xff09;在神经网络操作中占据主导地位&#xff0c;主要因为GPU针对MatMul进行了优化。 老黄一举揭秘三代GPU&#xff01;打破摩尔定律&#xff0c;打造AI帝国&#xff0c;量产Blackwell解决ChatGPT全球耗电难题 这种优化使…

【适配鸿蒙next】Flutter 新一代混合栈管理框架

前言 据最新消息显示&#xff0c;华为今年下半年将全面转向其自主平台HarmonyOS&#xff0c;放弃Android系统。 报道中提到&#xff0c;下一版HarmonyOS预计将随华为即将推出的Mate 70旗舰系列一起发布。 据悉&#xff0c;HarmonyOS Next 已经扩展到4000个应用程序&#xff0c;…

C++【STL】改造红黑树简单模拟实现set map(带你了解set map的底层实现结构)

目录 一、学前铺垫&#xff08;泛型编程&#xff09; 二、改造红黑树 1.红黑树节点的改造 2.insert的改造 3.迭代器的实现 4.完整改造代码 三、set的模拟实现封装 四、map的模拟实现封装 五、完结撒❀ 前言&#xff1a; 下面为了简单模拟实现set map所出现的代码是以…

Tensorflow入门实战 P03-天气识别

目录 1、完整代码 2、运行结果 2.1 查看20张图片 2.2 程序运行 2.3 运行结果 3、小结 ① 代码运行过程中有报错&#xff1a; ② 修改代码如下&#xff1a; ③ 分析原因&#xff1a; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&…

NDIS Filter开发-PNP响应和安装

NDIS filter驱动可能是最容易生成的驱动之一&#xff0c;如果你安装了VS 2015 WDK之后&#xff0c;你可以直接生成一个能运行的Filter驱动&#xff0c;它一般是ndislwf。 和大部分硬件不同&#xff0c;NDIS Filter驱动介于软件和硬件抽象层之上&#xff0c;它和硬件相关&…

SpringCloud Gateway中Route Predicate Factories详细说明

官网地址&#xff1a;https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.1.RELEASE/reference/html/#gateway-request-predicates-factories Spring Cloud Gateway将路由匹配作为Spring WebFlux HandlerMapping基础架构的一部分。 Spring Cloud Gateway …

使用 GPT-4 创作高考作文 2024年

使用 GPT-4 创作高考作文 2024年 使用 GPT-4 创作高考作文&#xff1a;技术博客指南 &#x1f914;✨摘要引言正文内容&#xff08;详细介绍&#xff09; &#x1f4da;&#x1f4a1;什么是 GPT-4&#xff1f;高考作文题目分析 ✍️&#x1f9d0;新课标I卷 人类智慧的进步&…

【C51】C51单片机实现的 抽奖机 设计与编程指南

文章目录 前言&#xff1a;1. 实现效果2. 准备工作3. 编写代码总结&#xff1a; 前言&#xff1a; 在本文中&#xff0c;我们将介绍如何使用C51单片机来实现一个简单的抽奖机。这个项目不仅能够展示C51单片机的基本应用&#xff0c;还能让我们了解如何通过编程来控制硬件&…

9.3 Go 接口的多态性

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:「stormsha的主页」…

Django 视图类

在Django框架中&#xff0c;视图类&#xff08;Class-based views&#xff0c;简称CBVs&#xff09;提供了一个面向对象的方式来定义视图。这种方式可以让你通过创建类来组织视图逻辑&#xff0c;而不是使用基于函数的视图&#xff08;Function-based views&#xff0c;简称FBV…

详解FedAvg:联邦学习的开山之作

FedAvg&#xff1a;2017年 开山之作 论文地址&#xff1a;https://proceedings.mlr.press/v54/mcmahan17a/mcmahan17a.pdf 源码地址&#xff1a;https://github.com/shaoxiongji/federated-learning 针对的问题&#xff1a;移动设备中有大量的数据&#xff0c;但显然我们不能收…

minio的一个基础使用案例:用户头像上传

文章目录 一、minio下载安装&#xff08;Windows&#xff09;二、案例需求分析三、后端接口开发 一、minio下载安装&#xff08;Windows&#xff09; 1. 下载minio服务端和客户端 minio下载地址 2. 手动搭建目录 /minio/binmc.exeminio.exe/data/logs手动创建minio应用程序目…

vivado HW_DEVICE

硬件设备 描述 在Vivado Design Suite的硬件管理器功能中&#xff0c;每个硬件目标都可以 具有一个或多个Xilinx FPGA设备进行编程或用于调试目的。这个 hw_device对象是通过hw_server打开的hw_target上的物理部分。这个 current_hw_device命令指定或返回当前设备。 相关对象 硬…

Linux—小小内核升级

本篇主要是讲述下关于内核的一些基本常识&#xff0c;并记录下内核升级和编译的过程&#xff0c;若有遗漏/有误之处&#xff0c;望各位大佬们指出。 Ⅰ 基本内核常识 常见内核安装包 内核(kernel)&#xff1a;这是Linux操作系统的核心部分&#xff0c;它负责管理系统的硬件和…