Collection与数据结构 顺序表与ArrayList

1. 线性表

线性表(linear list)是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列…
线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的,线性表在物理上存储时,通常以数组和链式结构的形式存储。
在这里插入图片描述

2. 顺序表

顺序表是一段物理空间连续的线性表,在底层一般使用数组来实现,在数组的基础上完成增删查改.下面是顺序表的一些接口.

2.1 接口

public interface Ilist {void add(int data);//为顺序表的尾部增加元素void add(int data ,int pos);//为指定位置添加元素void display();//打印顺序表int size ();//检测顺序表中元素的个数boolean contains(int toFind);//检测顺序表中是否包含该元素int indexOf(int toFind);//返回所要寻找第一个元素的下标int get(int index);//获取指定下标的元素void set(int index,int val);//把指定下标的元素指定为指定元素void remove(int toRomve);//移除第一个指定的元素void clear();//清空顺序表
}

下面我们来实现这些接口:

import java.util.Arrays;/*** 顺序表底层是用数组来实现的*/
public class MyArrayList implements Ilist {private int[] elem;private int size;//记录有效数据public static final int DEFAULT_CAPACITY = 5;//默认容量private boolean isFull(){return size == elem.length;//判断顺序表的容量是否为满}private void checkPos(int pos){if (pos < 0 || pos >= size){throw new PosException("pos is false");//判断插入位置是否合法}}private boolean isEmpty(){return this.size == 0;}public MyArrayList() {this.elem = new int[DEFAULT_CAPACITY];//默认容量为5this.size = 0;}//无参数的构造方法public void add(int data){//在末尾的位置添加元素if (isFull()){elem = Arrays.copyOf(elem,elem.length*2);//扩容}elem [size] = data;size++;}public void add(int data ,int pos){//在指定位置添加元素checkPos(pos);if (isFull()){elem = Arrays.copyOf(elem,elem.length*2);//扩容}for (int i = size-1; i >= pos ; i--) {//数组整体后移elem [i+1] = elem [i];}elem[pos] = data;size++;}public void display(){//打印顺序表System.out.print("["+" ");for (int i = 0; i < size; i++) {//打印有效元素System.out.print(elem[i]+" ");}System.out.print("]");}public int size (){//返回当前顺序表大小return this.size;}public boolean contains(int toFind){for (int i = 0; i < size; i++) {//在这里不可以用elem.length,后面的扩容之后未赋值if(elem[i] == toFind){return true;}}return false;}public int indexOf(int toFind){//返回要找的元素第一个返回的下标for (int i = 0; i < size; i++) {//在这里不可以用elem.length,后面的扩容之后未赋值if(elem[i] == toFind){return i;}}return -1;}public int get(int index){//获取index位置的值checkPos(index);if (isEmpty()){//存在默认容量5,若没有此方法,可能会在未初始化的位置上直接获取元素,获取成功//但是为0,不符合实际throw new EmptyException("array is empty");}return elem[index];}public void set(int index,int val){//把index位置的值改为valcheckPos(index);if (isEmpty()){//存在默认容量5,若没有此方法,可能会在未初始化的位置上直接添加元素,//添加成功,但是不符合实际throw new EmptyException("array is empty");}elem[index] = val;}public void remove(int toRomve){//移除第一次出现的元素if (isEmpty()){throw new EmptyException("array is empty");}int index = indexOf(toRomve);//先找到下标的位置for (int i = index+1; i < size; i++) {elem[i-1] = elem[i];}elem[size-1] = 0;size --;}public void clear(){size = 0;}
}```java
public class EmptyException extends NullPointerException{public EmptyException(String s) {super(s);}
}
public class PosException extends ArrayIndexOutOfBoundsException{public PosException(String s) {super(s);}
}

下面通过一些测试用例;来测试:

public class Main {public static void main(String[] args) {MyArrayList list = new MyArrayList();list.add(0);list.add(1);list.add(3);list.add(4);list.add(2,2);list.add(5);list.display();System.out.println(list.size());list.remove(2);list.display();System.out.println(list.size());}
}

在这里插入图片描述

3.ArrayList简介

在这里插入图片描述
[说明]

  1. ArrayList是以泛型的方式实现的,使用时必须先实例化.
  2. ArrayList的底层是一段连续的存储空间,并且可以动态扩容,是一个动态类型的顺序表.

4.ArrayList的使用

4.1 ArrayList的构造方法

方法解释
public ArrayList()无参构造方法
public ArrayList(int initialCapacity)指定顺序表初始容量
public ArrayList(Collection<? extends E> c)利用Collection中的容器来构造

关于第三个构造方法,不太好理解,我们下面来解释一下:ArrayList已经传入了泛型的参数,就是E,这里用来构造ArrayList的Collection类中的元素必须是E的子类.

ArrayList<Integer> list = new ArrayList<>();
ArrayList<Integer> list1 = new ArrayList<>(list);
ArrayList<Number> list2 = new ArrayList<>(list);
ArrayList<Integer> list3 = new ArrayList<>(10);

4.2 ArrayList常见操作

方法解释
boolean add(E e)在尾部添加元素
void add(int index,E element)在指定位置添加元素
boolean addAll(Collection<? extends E> c)把c中的元素全部添加到顺序表尾部
E remove(int index)移除指定位置的元素
boolean remove(Object o)移除遇到的第一个元素o
E get(int index)获取指定位置的元素
E set(int index,E element)把指定位置的元素设置为指定的值
void clear()清空顺序表
boolean contains(Object o)检测顺序表中是否包含o
int indexOf(Object o)返回第一个指定元素所在的下标
int lastIndexOf(Object o)从后向前找,返回第一个元素所在的下标
List subList(int fromIndex,int toIndex)截取指定范围的字符串,左闭右开

在这里说明一下两个remove方法的区别,避免混淆,第一个remove方法时移除指定位置的元素,传入的元素类型为int类型的数据,而第二个remove方法移除的是第一个遇到的元素,这里传入的参数类型是和顺序表泛型相同的类型,当一个顺序表中存储的是Integer类型的数据的时候,要注意区分下标和元素.
下面对上述方法进行演示:

public static void main(String[] args) {List<String> list = new ArrayList<>();list.add("JavaSE");list.add("JavaWeb");list.add("JavaEE");list.add("JVM");list.add("测试课程");System.out.println(list);// 获取list中有效元素个数System.out.println(list.size());// 获取和设置index位置上的元素,注意index必须介于[0, size)间System.out.println(list.get(1));list.set(1, "JavaWEB");System.out.println(list.get(1));// 在list的index位置插入指定元素,index及后续的元素统一往后搬移一个位置list.add(1, "Java数据结构");System.out.println(list);// 删除指定元素,找到了就删除,该元素之后的元素统一往前搬移一个位置list.remove("JVM");System.out.println(list);// 删除list中index位置上的元素,注意index不要超过list中有效元素个数,否则会抛出下标越界异常list.remove(list.size()-1);System.out.println(list);// 检测list中是否包含指定元素,包含返回true,否则返回falseif(list.contains("测试课程")){list.add("测试课程");}// 查找指定元素第一次出现的位置:indexOf从前往后找,lastIndexOf从后往前找list.add("JavaSE");System.out.println(list.indexOf("JavaSE"));System.out.println(list.lastIndexOf("JavaSE"));// 使用list中[0, 4)之间的元素构成一个新的SubList返回,但是和ArrayList共用一个elementData数组List<String> ret = list.subList(0, 4);System.out.println(ret);list.clear();System.out.println(list.size());
}

4.3 ArrayList的遍历

ArrayList有四种遍历方式,一种是通过sout直接输出,一种是for-i,一种是for-each,一种是使用迭代器.

import java.util.ArrayList;
import java.util.Iterator;
public class TestArrayList {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);//通过sout去遍历ArrayListSystem.out.println(list);//通过fori遍历for (int i = 0; i < list.size(); i++) {System.out.print(list.get(i)+" ");}System.out.println();//通过foreach遍历for (int x:list) {System.out.print(x+" ");}System.out.println();//通过迭代器遍历Iterator<Integer> iterator = list.iterator();while (iterator.hasNext()){System.out.print(iterator.next()+" ");}System.out.println();}
}

4.4 ArrayList扩容机制

ArrayList是动态的顺序表,在顺序表的容量不够的时候会自动扩容,下面是底层代码对ArrayList的扩容机制.

	public boolean add(E e) {modCount++;//底层是C/C++代码add(e, elementData, size);//调用另一个重载的add方法,指定添加容积return true;}private void add(E e, Object[] elementData, int s) {if (s == elementData.length)//容器满的时候需要扩容elementData = grow();//调用grow方法扩容elementData[s] = e;size = s + 1;}private Object[] grow() {return grow(size + 1);//最小容积是size+1,就是指定的添加容积+1}private Object[] grow(int minCapacity) {//传入指定的最小容积int oldCapacity = elementData.length;if (oldCapacity > 0 || elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {int newCapacity = ArraysSupport.newLength(oldCapacity,//对数组扩容minCapacity - oldCapacity, /* minimum growth */    //计算原容量和最小容积的差值oldCapacity >> 1  //原容量的一半         /* preferred growth */);return elementData = Arrays.copyOf(elementData, newCapacity);//正式扩容} else {return elementData = new Object[Math.max(DEFAULT_CAPACITY, minCapacity)];}}public static int newLength(int oldLength, int minGrowth, int prefGrowth) {// preconditions not checked because of inlining// assert oldLength >= 0// assert minGrowth > 0int prefLength = oldLength + Math.max(minGrowth, prefGrowth); // might overflow//若pre大,1.5被扩容,若是min大,直接加上指定的最小容积if (0 < prefLength && prefLength <= SOFT_MAX_ARRAY_LENGTH) {return prefLength;} else {// put code cold in a separate methodreturn hugeLength(oldLength, minGrowth);}}

[总结]

  1. 预估要扩容的大小
  • 初步预估按照1.5倍扩容.
  • 如果用户所需大小预估超过1.5,则按照用户所需大小扩容.
  1. 使用copyOf扩容.

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

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

相关文章

A Novel Negative Sample Generating Method for KnowledgeGraph Embedding

摘要 为了有效地提取知识图中的关系和原因&#xff0c;将实体和关系编码到一个连续的低维语义空间中。在负样本生成阶段&#xff0c;大多数知识图嵌入方法更注重替换头或尾实体以提高训练效率&#xff0c;很少替换关系。这些负样本生成方法对关系预测的贡献不大。本文提出了一…

vue项目在本地源码方式启动和打包之后在nginx中代理有什么不同

Vue项目在本地源码方式启动和打包之后在Nginx中代理的主要区别在于开发环境与生产环境的配置、性能优化、安全性和部署流程等方面。以下是一些具体的差异点&#xff1a; 开发环境与生产环境&#xff1a; 本地源码启动通常是在开发环境中&#xff0c;使用Vue CLI的vue-cli-servi…

瑞吉外卖实战学习--登录过滤器和判断是否登录过

完善登录功能 1、创建自定义过滤器LoginCheckFiler1.1通过WebFilter创建过滤器1.2 验证是否可以拦截请求1.3 代码 2、在启动类加入注解ServletComponentScan 用来扫描过滤器触发所有的过滤器ServletComponentScan 3、完善过滤器的处理逻辑3.1判断是否需要是要放行的请求3.2判断…

鸿蒙OS应用示例:【数字滚动计时】

实现效果&#xff1a; 代码示例&#xff1a; RollingText.ets 组件封装 RollingText.ets 组件封装 /*** 滚动文字特效*/ Component export default struct RollingText {private num:numberprivate timerId: number -1State counter: number 0aboutToAppear() {this.timerId…

Git基础(25):Cherry Pick合并指定commit id的提交

文章目录 前言指定commit id合并使用TortoiseGit执行cherry-pick命令 前言 开发中&#xff0c;我们会存在多个分支开发的情况&#xff0c;比如dev&#xff0c;test, prod分支&#xff0c;dev分支在开发新功能&#xff0c;prod作为生产分支已发布。如果某个时候&#xff0c;我们…

3.26C++

定义一个矩形类&#xff08;Rectangle&#xff09;&#xff0c;包含私有成员&#xff1a;长(length)、宽&#xff08;width&#xff09;, 定义成员函数&#xff1a; 设置长度&#xff1a;void set_l(int l) 设置宽度&#xff1a;void set_w(int w) 获取长度&#xff1a;int…

【Linux】线程同步{死锁/线程同步相关接口/由浅入深理解线程同步}

文章目录 1.死锁1.1概念1.2死锁的必要条件 2.线程同步相关接口2.1pthread_cond_init/destroy()2.2int pthread_cond_wait2. 3linux下的条件变量及其作用2.4int pthread_cond_signal/broadcast();2.5Linux下 阻塞和挂起的异同2.6阻塞&#xff0c;挂起&#xff0c;和进程切换的关…

【MySQL】数据库--基础

目录 一、概念&#xff1a; 二、连接数据库[Dos命令] 三、SQL 语句分类 一、概念&#xff1a; MySQL 是一种开源的关系数据库管理系统 (RDBMS)数据库-表的本质仍然是文件 二、连接数据库[Dos命令] mysql -h&#xff1a;mysql服务的主机&#xff08;默认连接到本机服务器&…

轻松掌握:使用 API 接口自动缩短网址的秘诀

在互联网的世界里&#xff0c;网址缩短已经成为了一种时尚和必要。长而复杂的网址不仅难以记忆&#xff0c;还可能让人望而却步。但是&#xff0c;现在有了 API 接口&#xff0c;我们可以轻松地将网址自动缩短&#xff0c;让分享变得更加简单和高效&#xff01;本文将以具体例子…

自增不再简单:深入探索MySQL自增ID的持久化之道

概述 MySQL中的自增特性估计大家或多或少都是用过。一张表中只能由一个自增字段&#xff0c;通常我们会把它设置为主键&#xff0c;但是随着大家系统越来越分布式&#xff0c;为了一些性能和可扩展性问题&#xff0c;大家目前选择更多的都是分布式ID&#xff08;雪花算法、UUI…

【python】Jupyter Notebook 修改默认路径

文章目录 一、修改前&#xff08;一&#xff09;问题&#xff08;二&#xff09;修改前的默认路径 二、修改配置文件、更改路径&#xff08;一&#xff09;找到配置文件并打开&#xff08;二&#xff09;创建目标文件夹、得到新的路径&#xff08;三&#xff09;修改配置文件 三…

大模型时代的向量数据库:原理解析和应用案例

大家好&#xff0c;在人工智能领域&#xff0c;数据处理和加工的需求愈发增加。随着人们深入探索AI高级的应用&#xff0c;如图像识别、语音搜索和推荐引擎等&#xff0c;数据的复杂性也在不断地增加。此时传统的数据库存储方式已不能完全满足需求&#xff0c;向量数据库应运而…

su怎么做展厅模型---模大狮模型网

要在SketchUp中创建展厅模型&#xff0c;你可以按照以下基本步骤进行&#xff1a; 绘制基本结构&#xff1a; 使用SketchUp的绘图工具(线条、矩形、圆形等)来创建展厅的基本结构&#xff0c;包括墙壁、地板和天花板等。确保按照实际尺寸和比例进行绘制。 添加家具和展品&…

【C++教程从0到1入门编程】第十三篇:STL中list类的模拟实现

一、list的模拟实现 #include<iostream> #include<assert.h> #pragma once namespace jyr {template<class T>struct _list_node{_list_node<T>* _next;_list_node<T>* _prev;T _data;_list_node(const T& val T()):_next(nullptr), _prev(…

Zabbix 配置使用

目录 配置流程 添加组机组 添加模板 添加主机 配置图形 配置大屏 Monitoring 配置地图 最新数据 故障 使用IT服务 使用报表 资产管理 全局搜索 导入导出 用户权限 用户组权限 用户 匿名用户 调试模式 与 LDAP 对接 维护模式 故障确认 批量更新 配置流程…

【办公类-21-10】三级育婴师 视频转文字docx(等线小五单倍行距),批量改成“宋体小四、1.5倍行距、蓝色字体、去掉五分钟”

作品展示 背景需求 今天将最后3个育婴师操作视频做整理 第1步&#xff1a;视频MP4转MP3 【办公类-40-01】20240311 用Python将MP4转MP3提取音频 &#xff08;家长会系列一&#xff09;-CSDN博客文章浏览阅读393次&#xff0c;点赞9次&#xff0c;收藏6次。【办公类-40-01】20…

[项目前置]websocket协议

websocket协议介绍 WebSocket 协议是一种在单个 TCP 连接上进行全双工通讯的协议。 WebSocket 使得客户端和服务器之间的数据交换变得更简单&#xff0c;允许服务器主动向客户端推送数据。它在 2011 年成为国际标准&#xff0c;现在被所有现代浏览器支持。WebSocket 设计用于…

iNet Network Scanner Mac 网络扫描工具

iNet Network Scanner for Mac是一款功能强大的网络扫描工具&#xff0c;专为Mac用户设计。它提供了全面而深入的网络分析功能&#xff0c;使用户能够轻松获取Mac连接的网络和设备的详细信息。 软件下载&#xff1a;iNet Network Scanner Mac v3.1.0激活版 这款软件具备多种扫描…

业务服务:xss攻击

文章目录 前言一、使用注解预防1. 添加依赖2. 自定义注解3. 自定义校验逻辑4. 使用 二、使用过滤器1. 添加配置2. 创建配置类3. 创建过滤器4. 创建过滤器类5. 使用 前言 xss攻击时安全领域中非常常见的一种方法&#xff0c;保证我们的系统安全是非常重要的 xss攻击简单来说就…

TCP(socket 套接字)编程 1

一、TCP套接字编程架构如下 二、相关代码实现 1、服务器端代码 package com.company;import java.io.IOException; import java.net.InetSocketAddress; import java.net.ServerSocket; import java.net.Socket;public class Main {public static void main(String[] args) {…