Java顺序表解析与应用

一、顺序表概念

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

二、主要功能接口实现

Java顺序表底层就是一个动态数组。其主要功能接口如下:

// 1.打印顺序表,注意:该方法并不是顺序表中的方法,为了方便看测试结果给出的
public void display() { }
// 2.新增元素,默认在数组最后新增
public void add(int data) { }
// 3.判断当前的顺序表是不是满的
public boolean isFull() { }
// 4.在 pos 位置新增元素
public void add(int pos, int data) { }
// 5.判定是否包含某个元素
public boolean contains(int toFind) { return true; }
// 6.查找某个元素对应的位置
public int indexOf(int toFind) { return -1; }
// 7.获取 pos 位置的元素
public int get(int pos) { return -1; }
// 8.给 pos 位置的元素设为 value
public void set(int pos, int value) { }
// 9.删除第一次出现的关键字 key
public void remove(int toRemove) { }
// 10.获取顺序表长度
public int size() { return 0; }
// 11.清空顺序表
public void clear() { }

下面我们对应上面的功能接口,自己实现一下顺序表(由于这部分比较简单这里就直接给出代码,大家可结合注释参考。另外此处侧重于流程实现,使用了更好理解的int类型,并未使用泛型):

import java.util.Arrays;
public class MyArraylist {public int[] elem;// 已使用容量,初始为0public int usedSize;// 默认容量private static final int DEFAULT_SIZE = 5;// 这里采用无参的构造方法public MyArraylist() {this.elem = new int[DEFAULT_SIZE];}/*** 1.打印顺序表  * 注意:该方法并不是顺序表中的方法,为了方便看测试结果给出的* 根据usedSize判断即可*/public void display() {for (int i = 0; i < this.usedSize; i++) {System.out.print(this.elem[i] + " ");}}/*** 2.新增元素,默认尾插*/ public void add(int data) {if (isFull()) {resize();}this.elem[this.usedSize] = data;this.usedSize++;}// 扩容private void resize() {this.elem = Arrays.copyOf(this.elem, 2 * this.elem.length);}// 检查坐标合法性private void checkPosInAdd(int pos) {if (pos < 0 || pos > this.usedSize) {// 这里自定义异常类throw new IndexException("位置不合法,请检查位置的合法性!");}}/*** 3.判断当前的顺序表是不是满的*/public boolean isFull() {return this.usedSize == this.elem.length;}/*** 4.在 pos 位置新增元素!*/public void add(int pos, int data) {if (isFull()) {resize();}checkPosInAdd(pos);for (int i = this.usedSize; i > pos; i--) {this.elem[i] = this.elem[i - 1];}this.elem[pos] = data;this.usedSize++;}/*** 5.判定是否包含某个元素*/public boolean contains(int toFind) {for (int i = 0; i < this.usedSize; i++) {if (this.elem[i] == toFind) {return true;}}return false;}/*** 6.查找某个元素对应的位置*/public int indexOf(int toFind) {for (int i = 0; i < this.usedSize; i++) {if (this.elem[i] == toFind) {return i;}}return -1;}/*** 7.获取 pos 位置的元素*/public int get(int pos) {checkPosInAdd(pos);return this.elem[pos];}// 判空private boolean isEmpty() {if (this.usedSize == 0) {return true;}return false;}/*** 8.将 pos 位置的元素设为修改为: value*/public void set(int pos, int value) {checkPosInAdd(pos);this.elem[pos] = value;}/*** 9.删除第一次出现的关键字key*/public boolean remove(int key) {int index = indexOf(key);if (index == -1) {System.out.println("不存在关键字" + key);return false;}for (int j = index; j < this.usedSize - 1; j++) {this.elem[j] = this.elem[j + 1];}this.usedSize--;//注意:是在这条语句之后//elem[usedSize] = null;// 如果里面是引用类型 那么此时就需要手动置空elem[usedSize] = 0;return true;}/*** 10.获取顺序表长度*/ public int size() {return this.usedSize;}/*** 11.清空顺序表*/ public void clear() {this.usedSize = 0;}
}

上述过程中自定义的异常类:

public class IndexException extends RuntimeException {// 帮助父类构造IndexException() {super();}IndexException(String msg) {super(msg);}
}

三、Java集合框架中的 ArrayList

java.util 包下为我们提供了一个ArrayList类,ArrayList底层是一段连续的空间,并且可以动态扩容,是一个动态类型的顺序表,且这里的 ArrayList 是以泛型方式实现的,使用时必须要先实例化。此外在Java中还对ArrayList有以下这些说明:(现阶段不做解释,大家可以暂时了解即可)

  1. ArrayList实现了RandomAccess接口,表明ArrayList支持随机访问
  2. ArrayList实现了Cloneable接口,表明ArrayList是可以clone的
  3. ArrayList实现了Serializable接口,表明ArrayList是支持序列化的
  4. 和Vector不同,ArrayList不是线程安全的,在单线程下可以使用,在多线程中可以选择Vector或者 CopyOnWriteArrayList

1、ArrayList的构造方法

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

解释:

  1. 对于无参构造方法ArrayList(),在实例化ArrayList对象时不会分配内存,在add()方法中才进行内存分配。
  2. 对于ArrayList(Collection<? extends E> c),表示可以将实现了Collection接口、并且是E类型或E类型的子类的集合作为参数构造ArrayList。
  3. 相比之下ArrayList(int initialCapacity)就比较好理解了,这个构造方法是在实例化ArrayList对象时,分配指定initialCapacity大小的容量。

2、ArrayList常用方法

与此同时,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 isEmpty()如果此列表不包含元素,则返回 true
int size()返回此列表中的元素数
boolean contains(Object o)判断 o 是否在线性表中
int indexOf(Object o)返回第一个 o 所在下标
int lastIndexOf(Object o)返回最后一个 o 的下标
List subList(int fromIndex, int toIndex)截取部分 list

3、ArrayList 的继承关系

在《Java集合框架中》我们介绍了Java集合中的继承关系,你是否还有印象ArrayList实现了List接口:

对于List接口来说,里面涵盖了ArrayList中的方法,也就是说我们可以使用 List 接口对 ArrayList 实例进行操作,因此我们可以写出类似这种调用方式:List<Integer> list = new Arraylist<>(); 将ArrayList实例交给List接口,然后直接使用list进行相关操作。

public class OperateTest {public static void main(String[] args) {List<Integer> list = new ArrayList<>();list.add(111);list.add(222);list.add(333);list.add(444);list.add(555);System.out.println(list);// 设定list2->[1,2,3] 便于测试addAll()List<Integer> list2 = new ArrayList<>();list2.add(1);list2.add(2);list2.add(3);// 末尾插入list2list.addAll(list2);System.out.println(list);// 获取list中有效元素个数System.out.println(list.size());// 获取和设置index位置上的元素,注意index必须介于[0, size)间System.out.println(list.get(0));list.set(0, 999);System.out.println(list.get(0));// 在list的index位置插入指定元素,index及后续的元素统一往后搬移一个位置list.add(1, 888);System.out.println(list);// 删除指定元素,找到了就删除,该元素之后的元素统一往前搬移一个位置// (这里如果直接写444会默认下标,需要使用引用类型)list.remove(new Integer(444));System.out.println(list);// 删除list中index位置上的元素,注意index不要超过list中有效元素个数,否则会抛出下标越界异常list.remove(list.size()-1);System.out.println(list);// 检测list中是否包含指定元素,包含返回true,否则返回falseif(!list.contains(123456)){list.add(123456);System.out.println(list);}// 查找指定元素第一次出现的位置:indexOf从前往后找,lastIndexOf从后往前找System.out.println(list.indexOf(333));System.out.println(list.lastIndexOf(333));// 使用list中[0, 4)之间的元素构成一个新的SubList返回,// 但是和ArrayList共用一个elementData数组(对任一部分修改会影响整个部分)List<Integer> ret = list.subList(0, 2);System.out.println(ret);// 清空list.clear();System.out.println(list.size());}
}

4、ArrayList的遍历

(1) 方式一:
使用for循环+下标遍历

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

(2) 方式二:
由于List、Arraylist集合实现了iterable接口,可以使用增强的for循环-foreach

for (Integer x:list) {System.out.println(x);
}

(3) 方式三:
对于Java而言只要实现了Iterable接口的集合就可以使用迭代器 iterator

Iterator<Integer> it = list.listIterator();
while(it.hasNext()){System.out.println(it.next());
}

总结

本篇文章主要介绍了 Java 集合中的线性结构 ArrayList ,这是一个相对比较简单,且容易理解和实现的数据结构。这里就简单总结一下顺序表 ArrayList的优缺点:

顺序表缺点:

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

顺序表优点:

  1. 当给定下标的时候,查找速度非常快,复杂度为O(1)

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

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

相关文章

手势识别-手势音量控制(opencv)

本项目是使用了谷歌开源的框架mediapipe&#xff0c;里面有非常多的模型提供给我们使用&#xff0c;例如面部检测&#xff0c;身体检测&#xff0c;手部检测等。 代码需要用到opencv HandTraqckModule模块 mediapipe模块和一个音量控制模块 AndreMiras/pycaw: Python Core…

手机便签中可以打勾的圆圈或小方块怎么弄?

在日常的生活和工作中&#xff0c;很多网友除了使用手机便签来记录灵感想法、读书笔记、各种琐事、工作事项外&#xff0c;还会用它来记录一些清单&#xff0c;例如待办事项清单、读书清单、购物清单、旅行必备物品清单等。 在按照记录的清单内容来执行的时候&#xff0c;为了…

$bus的emit和on执行顺序

需求&#xff1a; 但是发现弹框组件第一次打开时&#xff0c;接收不到信息&#xff0c;第二次再摊开&#xff0c;就收到消息了。 原因是因为&#xff1a; 是因为全局事件总线必须先执行$on,再执行$emit 所以我们在使用$bus.$emit发送消息时&#xff0c;要使用nextTick包裹&…

全栈开发流程——数据表的分析与创建详解实战演示(一)

作者介绍 「作者主页」&#xff1a;雪碧有白泡泡 「个人网站」&#xff1a;雪碧的个人网站 「推荐专栏」&#xff1a; ★java一站式服务 ★ ★ React从入门到精通★ ★前端炫酷代码分享 ★ ★ 从0到英雄&#xff0c;vue成神之路★ ★ uniapp-从构建到提升★ ★ 从0到英雄&…

【windows】windows上如何使用linux命令?

前言 windows上的bat命令感觉不方便&#xff0c;想在windows上使用linux命令。 有人提供了轮子&#xff0c;本文简单介绍一些该轮子的安装与使用&#xff0c;希望能够帮助到和我有一起需求的网友。 我的答案是busybox。 1.安装busybox.exe 在这个网站上安装busybox busyb…

【gridsample】地平线如何支持gridsample算子

文章目录 1. grid_sample算子功能解析1.1 理论介绍1.2 代码分析1.2.1 x,y取值范围[-1,1]1.2.2 x,y取值范围超出[-1,1] 2. 使用grid_sample算子构建一个网络3. 走PTQ进行模型转换与编译 实操以J5 OE1.1.60对应的docker为例 1. grid_sample算子功能解析 该段主要参考&#xff1a;…

Unity 编辑器资源导入处理函数 OnPreprocessAudio :深入解析与实用案例

Unity 编辑器资源导入处理函数 OnPreprocessAudio 用法 点击封面跳转下载页面 简介 在 Unity 中&#xff0c;资源导入是一个非常重要的环节&#xff0c;它决定了资源在项目中的使用方式和效果。Unity 提供了一系列的资源导入处理函数&#xff0c;其中之一就是 OnPreprocessAud…

线性代数(三) 线性方程组

前言 如何利用行列式&#xff0c;矩阵求解线性方程组。 线性方程组的相关概念 用矩阵方程表示 齐次线性方程组&#xff1a;Ax0&#xff1b;非齐次线性方程组&#xff1a;Axb. 可以理解 齐次线性方程组 是特殊的 非齐次线性方程组 如何判断线性方程组的解 其中R(A)表示矩阵A的…

主数据管理案例-中国外运

1、 背景介绍及难点分析 作为世界领先的物流行业整合商、端到端的全程供应链解决方案和一站式物流服务提供商&#xff0c;中国外运非常重视信息化建设&#xff0c;先后投资建设了 300多个信息系统&#xff0c;为中国外运的内部管理和业务运作提供 IT 支持和保障。 由于缺乏统一…

进程间通信的编程方式(IPC)及实验

进程间通信&#xff08;IPC&#xff09;方式 目录 Socket 管道 匿名管道 消息队列 共享内存 信号 远程过程调用 Socket Socket编程是一种在计算机网络中进程间通信的编程方法。Socket提供了一种在不同主机上运行的进程之间传输数据的机制。通过使用Socket API&#xff…

Effective Java笔记(30)优先考虑泛型方法

正如类可以从泛型中受益一般 &#xff0c;方法也一样。静态工具方法尤其适合于泛型化 。 Collections 中的所有“算法”方法&#xff08;例如 binarySearch 和 sort &#xff09;都泛型化了 。 编写泛型方法与编写泛型类型相类似 。 例如下面这个方法&#xff0c;它返回两个集合…

iOS问题记录 - Xcode 15安装低版本iOS模拟器(持续更新)

文章目录 前言开发环境问题描述问题分析1. 定位问题2. 逆向分析2.1. IDA Free2.2. Hopper Disassembler Demo 3. 模拟器日志4. supportedArchs 解决方案最后 前言 最近新需求很多&#xff0c;项目改动很大&#xff0c;开发完成后想测一遍在低版本iOS系统上的兼容性&#xff0c…

分享21年电赛F题-智能送药小车-做题记录以及经验分享

这里写目录标题 前言一、赛题分析1、车型选择2、巡线1、OpenMv循迹2、灰度循迹 3、装载药品4、识别数字5、LED指示6、双车通信7、转向方案1、开环转向2、位置环速度环闭环串级转向3、MPU6050转向 二、调试经验分享1、循迹2、识别数字3、转向4、双车通信5、逻辑处理6、心态问题 …

Docker卸载安装及国内镜像源(详细版)

文章目录 一、卸载已有Docker1、首先判断本地有没有docker&#xff1a;2、判断CentOS下 docker是否在运行&#xff1a;3、停止docker运行&查看状态4、yum查看docker安装的包并卸载5、删除docker安装目录6、查看docker version 二、Docker安装及镜像源配置1、centOS 7 yum源…

Jay17 2023.8.10日报

笔记 【python反序列化】 序列化 类对象->字节流&#xff08;字符串&#xff09; 反序列化 字节流->对象 python反序列化没PHP这么灵活&#xff0c;没这么多魔术方法。 import pickle import os class ctfshow(): def init(self): self.username0 self.password0 d…

【数理知识】求刚体旋转矩阵和平移矩阵,已知 N>=3 个点在前后时刻的坐标,且这 N>=3 点间距离始终不变代表一个刚体

序号内容1【数理知识】自由度 degree of freedom 及自由度的计算方法2【数理知识】刚体 rigid body 及刚体的运动3【数理知识】刚体基本运动&#xff0c;平动&#xff0c;转动4【数理知识】向量数乘&#xff0c;内积&#xff0c;外积&#xff0c;matlab代码实现5【数理知识】最…

轻松预约,尽享美食,详解餐厅预约小程序的设计与实现

随着智能手机的普及和人们生活水平的提高&#xff0c;餐厅预约已经成为人们日常生活中的一部分。为了更好地满足人们的需求&#xff0c;许多餐厅开始使用小程序来提供更方便快捷的预约服务。本文将介绍如何制作一款餐厅预约小程序的详细步骤。 1. 进入乔拓云网后台&#xff0c;…

uni-app微信小程序开发自定义select下拉多选内容篇

分享-2023年资深前端进阶&#xff1a;前端登顶之巅-最全面的前端知识点梳理总结 *分享一个使用比较久的&#x1fa9c; 技术框架公司的选型&#xff1a;uni-app uni-ui vue3 vite4 ts 需求分析&#xff1a;微信小程序-uni-ui内容 1、创建一个自定义的下拉&#xff0c;支持多…

OSPF无法建立领居的原因有哪些(第三十五课)

1 配置OSPF 1.1 思路 1&#xff0c;配置IP地址 2&#xff0c;配置OSPF 配置进程号 route-id进入区域宣告网段 配置IP地址 R1路由表 ------------------------------------------------------------------------------ Routing Tables: Public Destinations : 10 …