【数据结构】顺序表与ArrayList

作者主页:paper jie 的博客

本文作者:大家好,我是paper jie,感谢你阅读本文,欢迎一建三连哦。

本文录入于《JAVA数据结构》专栏,本专栏是针对于大学生,编程小白精心打造的。笔者用重金(时间和精力)打造,将javaSE基础知识一网打尽,希望可以帮到读者们哦。

其他专栏:《算法详解》《C语言》《javaSE》等

内容分享:本期将会对数据结构中的顺序表进行讲解

目录

线性表

顺序表

简单顺序表的模拟实现

集合框架

ArrayList介绍

ArrayList的使用

ArrayList的构造

ArrayList的基本方法

ArrayList的遍历

ArrayList的扩容机制

画图分析

ArrayList的具体使用

顺序表ArrayList存储结构的优缺点


线性表

线性表就是有多个相同属性的数据元素的有限序列。线性表是一种在我们工作中广泛可以使用到的数据结构,常见的线性表:顺序表,链表,栈,队列……

线性表在逻辑上是线性结构,是一条连续的直线。但是它在物理结构上可可能不是连续的。线性表在物理上存储时,一般是以数组和链式结构的方式存储。

顺序表

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

简单顺序表的模拟实现

大家可以移步到我的Gitee上看代码,有点多,这里就不展示了:structure_code/java2023.9.12/src/mylist · 彭子杰/数据结构 - 码云 - 开源中国 (gitee.com)

集合框架

java集合框架,也称为容器,是定义在java.util包下的一组接口interfaces和其实现类class。它是要的作用是将多个元素element置于一个单元中,用于对这些元素进行快速,便捷的存储store,检索retrieve,管理manipulate,即平时我们说的增删查改。

类与接口总览:

ArrayList介绍

在java的集合框架(容器)中,ArrayList就是一个顺序表,它是一个普通的类,实现了List接口,框架如下:

注意:

ArrayList是以泛型方式实现的,使用时需要先实例化

ArrayList实现了RandomAccess接口,表明ArrayList支持随机访问

ArrayList实现了cloneble接口,表明ArrayList是可以clone的

ArrayList实现了Serializable接口,表明ArrayList是支持序列化的

和Vector不同,ArrayList不是线程安全的,在单线程下可以使用,在多线程中可以选择Vector或者CopyOnWriteArrayList

ArrayList底层是一段连续的空间,并且可以动态扩容,是一个动态类型的顺序表

ArrayList的使用

ArrayList的构造

public class Test {public static void main(String[] args) {
// ArrayList创建,推荐写法
// 构造一个空的列表List<Integer> list1 = new ArrayList<>();
// 构造一个具有10个容量的列表List<Integer> list2 = new ArrayList<>(10);list2.add(1);list2.add(2);list2.add(3);
// list2.add("hello"); // 编译失败,List<Integer>已经限定了,list2中只能存储整形元素
// list3构造好之后,与list中的元素一致ArrayList<Integer> list3 = new ArrayList<>(list2);
// 避免省略类型,否则:任意类型的元素都可以存放,使用时将是一场灾难List list4 = new ArrayList();list4.add("111");list4.add(100);}
}

ArrayList的基本方法

    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);} // 查找指定元素第一次出现的位置: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());
}

ArrayList的遍历

ArrayList可以使用三个方式来遍历:for循环,foreach,迭代器

    public static void main(String[] args) {List<Integer> list = new ArrayList<>();list.add(1);list.add(2);list.add(3);list.add(4);list.add(5);
// 使用下标+for遍历for (int i = 0; i < list.size(); i++) {System.out.print(list.get(i) + " ");} System.out.println();
// 借助foreach遍历for (Integer integer : list) {System.out.print(integer + " ");} System.out.println();
// 使用迭代器遍历        Iterator<Integer> it = list.listIterator();while(it.hasNext()){System.out.print(it.next() + " ");} System.out.println();}

这里的迭代器是设计模式的一种。

ArrayList的扩容机制

 首选我们来看一段代码:

public static void main(String[] args) {List<Integer> list = new ArrayList<>();for (int i = 0; i < 100; i++) {list.add(i);}}

我们知道,ArrayList是一个动态类型的顺序表,即:在插入元素的过程中会自动扩容。我们可以看一下源码:

Object[] elementData; // 存放元素的空间
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; // 默认空间
private static final int DEFAULT_CAPACITY = 10; // 默认容量大小
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
private static int calculateCapacity(Object[] elementData, int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
return Math.max(DEFAULT_CAPACITY, minCapacity);
} r
eturn minCapacity;
}
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
private void grow(int minCapacity) {
// 获取旧空间大小
int oldCapacity = elementData.length;
// 预计按照1.5倍方式扩容
int newCapacity = oldCapacity + (oldCapacity >> 1);
// 如果用户需要扩容大小 超过 原空间1.5倍,按照用户所需大小扩容
if (newCapacity - minCapacity < 0) 
newCapacity = minCapacity;
// 如果需要扩容大小超过MAX_ARRAY_SIZE,重新计算容量大小
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// 调用copyOf扩容
elementData = Arrays.copyOf(elementData, newCapacity);
}
private static int hugeCapacity(int minCapacity) {
// 如果minCapacity小于0,抛出OutOfMemoryError异常
if (minCapacity < 0)
throw new OutOfMemoryError();
return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE;
}

画图分析

【总结】

检查是否真正需要扩容,如果是g调用了row准备扩容

估计需要库容的大小

初步按照1.5倍的大小扩容

如果用户需要的大小超过1.5倍,则按照用户所需大小扩容

真正扩容之前检查是否可以扩容成功,防止太大导致扩容失败

使用copyof进行扩容

ArrayList的具体使用

这里举一个简单的洗牌算法:

public class Card {
public int rank; // 牌面值
public String suit; // 花色
@Override
public String toString() {
return String.format("[%s %d]", suit, rank);
}
}import java.util.List;
import java.util.ArrayList;
import java.util.Random;
public class CardDemo {
public static final String[] SUITS = {"♠", "♥", "♣", "♦"};
// 买一副牌
private static List<Card> buyDeck() {
List<Card> deck = new ArrayList<>(52);
for (int i = 0; i < 4; i++) {
for (int j = 1; j <= 13; j++) {
String suit = SUITS[i];
int rank = j;
Card card = new Card();
card.rank = rank;
card.suit = suit;
deck.add(card);
}
} 
return deck;
}
private static void swap(List<Card> deck, int i, int j) {
Card t = deck.get(i);
deck.set(i, deck.get(j));
deck.set(j, t);
}
private static void shuffle(List<Card> deck) {
Random random = new Random(20190905);
for (int i = deck.size() - 1; i > 0; i--) {
int r = random.nextInt(i);
swap(deck, i, r);
}
}
public static void main(String[] args) {
List<Card> deck = buyDeck();
System.out.println("刚买回来的牌:");
System.out.println(deck);
shuffle(deck);
System.out.println("洗过的牌:");
System.out.println(deck);
// 三个人,每个人轮流抓 5 张牌
List<List<Card>> hands = new ArrayList<>();
hands.add(new ArrayList<>());
hands.add(new ArrayList<>());
hands.add(new ArrayList<>());
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 3; j++) {
hands.get(j).add(deck.remove(0));
}
} 
System.out.println("剩余的牌:");
System.out.println(deck);
System.out.println("A 手中的牌:");
System.out.println(hands.get(0));
System.out.println("B 手中的牌:");
System.out.println(hands.get(1));
System.out.println("C 手中的牌:");
System.out.println(hands.get(2));
}
}

顺序表ArrayList存储结构的优缺点

优点

不用为了表达清楚元素之间的关系而增加额外的存储空间。

可以快速地存取表中的任意一个位置的元素

缺点

在任位置删除插入元素的时间复杂度为O(N),所以需要移动大量的元素

当顺序表长度变化较大时,难以确定存储空间的容量。

容易造成存储空间的碎片,也就是浪费空间。

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

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

相关文章

Chinese-LLaMA-AIpaca

文章目录 关于 Chinese-LLaMA-Alpaca一、LLaMA模型 --> HF格式二、合并LoRA权重,生成全量模型权重方式1:单LoRA权重合并方式2:多LoRA权重合并(适用于Chinese-Alpaca-Plus )三、使用 Transformers 进行推理四、使用 webui 搭建界面1、克隆text-generation-webui并安装必…

企业图档加密系统

机械制造行业数据安全 机械制造企业对于设计工艺的能力要求非常高&#xff0c;其生产工业会涉及到大量设计图纸文档信息&#xff0c;一旦发生产品图纸丢失泄密情况&#xff0c;将造成重大损失。如何用技术手段保护企业的核心数据&#xff0c;保证企业的信息资料不会被无意或恶…

Clock Domain Crossing Design Verification Techniques Using System Verilog 学习

重要的设计考虑因素要求仔细构建多时钟设计时钟域交叉 (CDC) 边界。 本文详细介绍了一些最新策略和解决跨 CDC 边界传递一个或多个信号的最佳已知方法。论文中包含与 CDC 验证相关的技术和一个有趣的 2 深 FIFO用于在时钟域之间传递多个控制信号的设计。 虽然设计方法论文中描述…

WebGL 用鼠标控制物体旋转

目录 鼠标控制物体旋转 如何实现物体旋转 示例程序&#xff08;RotateObject.js&#xff09; 代码详解 示例效果 鼠标控制物体旋转 有时候&#xff0c;WebGL程序需要让用户通过鼠标操作三维物体。这一节来分析示例程序RotateObject&#xff0c;该程序允许用户通过拖动&…

2023华为杯研究生数学建模竞赛选题建议+初步分析

如下为C君的2023华为杯研究生数学建模竞赛&#xff08;研赛&#xff09;选题建议初步分析 2023华为杯研究生数学建模竞赛&#xff08;研赛&#xff09;选题建议 提示&#xff1a;DS C君认为的难度&#xff1a;CE<D<F&#xff0c;开放度&#xff1a;CDE<F。 华为专项…

1600*A. LCM Challenge(数论 || 找规律)

解析&#xff1a; n<3&#xff0c;特判 n为奇数&#xff0c;则n、n-1、n-2必定互质&#xff0c;所以结果即为三者之和。 n为偶数&#xff0c; 不会严格证明原因&#xff0c;但是找找规律&#xff0c;是这样的...... #include<bits/stdc.h> using namespace std; #de…

数据科学的文本技术 Text Technology(IR信息检索、搜索引擎)

一、文章摘要 1. 内容 * Introduction to IR and text processing, system components * Zipf, Heaps, and other text laws * Pre-processing: tokenization, normalisation, stemming, stopping. * Indexing: inverted index, boolean and proximity search * Evaluation m…

【RocketMQ专题】快速实战及集群架构原理详解

目录 课程内容一、MQ简介基本介绍*作用&#xff08;解决什么问题&#xff09; 二、RocketMQ产品特点2.1 RocketMQ介绍2.2 RocketMQ特点2.3 RocketMQ的运行架构2.4 消息模型 三、RocketMQ快速实战3.1 快速搭建RocketMQ服务3.2 快速实现消息收发3.3 搭建Maven客户端项目3.4 搭建R…

vue+axios+el-progress(elementUI组件)实现下载进度条实时监听(小白简洁版)

一、实现效果 二、实现方式 方案&#xff1a;使用axios方法onDownloadProgress方法监听下载进度 使用此方式的前提&#xff01;&#xff01;&#xff01;请让后端在响应头中加上content-length&#xff0c;存放下载文件的总大小&#xff0c;如下图&#xff1a; 三、代码 1、进…

U盘格式化后数据能恢复吗?详细答案看这里!

“U盘格式化之后数据还可以恢复吗&#xff1f;这真的困扰了我好久!之前由于u盘中病毒&#xff0c;不得已将它格式化了&#xff0c;但是我还有好多视频、图片都保存在里面&#xff0c;这该怎么办呢&#xff1f;” 小小的u盘&#xff0c;可是给我们带来了很多的便利的。在互联网时…

【直播预约中】 腾讯大数据 x StarRocks|构建新一代实时湖仓

随着信息时代的兴起&#xff0c;数据已成为推动业务决策和创新的核心要素&#xff1b;结构化、半结构化等多种类型的数据呈现爆炸式增长&#xff0c;如何高效处理和分析海量数据已经成为关键挑战&#xff0c;结合传统数仓与数据湖优势的湖仓一体&#xff08;Lakehouse&#xff…

uni-app打包iOS ipa文件后不上架App store为用户提供下载解决过程记录

写在前面&#xff0c;itms-services协议是什么 itms-services协议是苹果提供的一种让iOS应用在用户设备上无线安装或升级的协议。 具体来说: itms-services表示iOS应用无线安装服务的URL方案,格式为:itms-services://?actiondownload-manifest&urlMANIFEST_URL其中MANIF…

鼠标移入展示字体操作

鼠标移入展示字体 点击删除实行删除操作&#xff0c;点击图片文字跳转产品详情的逻辑实现 <div class"allProduct-content"><template v-for"(item, index) in obj.product" :key"index"><!-- <img :src"item.image&qu…

element收缩已经展开的菜单

问题描述 VUE菜单有一个BUG&#xff0c;当我们点击其它按钮或者首页的时候&#xff0c;已经展示的一级菜单是不会自动收缩的。这个问题也导致很多开发者把一级菜单都换成了二级菜单。 错误展示 错误的效果请看下图。 解决方法 1、寻找菜单文件 因为我使用的是ruoyi的前端框…

【AI视野·今日NLP 自然语言处理论文速览 第三十五期】Mon, 18 Sep 2023

AI视野今日CS.NLP 自然语言处理论文速览 Mon, 18 Sep 2023 Totally 51 papers &#x1f449;上期速览✈更多精彩请移步主页 Daily Computation and Language Papers "Merge Conflicts!" Exploring the Impacts of External Distractors to Parametric Knowledge Gra…

Zygote Secondary:加速应用启动的未来之路

Zygote Secondary&#xff1a;加速应用启动的未来之路 1. 引言 在现代的移动应用开发中&#xff0c;启动速度和响应性能是用户体验的重要方面。然而&#xff0c;传统的 Android 进程管理方式在启动应用时会出现性能瓶颈&#xff0c;导致启动时间过长和资源占用过多。为了解决…

更新GitLab上的项目

更新GitLab上的项目 如有需要&#xff0c;请参考这篇&#xff1a;上传项目到gitlab上 1.打开终端&#xff0c;进入到本地项目的根目录。 2.如果你还没有将远程GitLab仓库添加到本地项目&#xff0c;你可以使用以下命令&#xff1a; 比如&#xff1a; git remote add origin …

聊聊API安全的重要性及治理思路

在应用程序开发过程中&#xff0c;API是一个会被经常提及的东西&#xff0c;它的全称是Application Programming Interface&#xff08;应用程序接口&#xff09;&#xff0c;一般指的是Web API&#xff0c;即&#xff1a;采用HTTP通信协议的API或者是Web应用程序对外提供的API…

vue3项目学习一:创建vue3项目

创建vue3项目 一、使用vue-cli创建vue3项目1.安装vue-cli2.创建vue3项目 二、初始化项目结构三、导入element-ui 一、使用vue-cli创建vue3项目 1.安装vue-cli 先查看是否安装vue-cli 在cmd窗口输入vue -V查看版本&#xff0c;如果出现 则说明存在vue-cli,如果出现 则需要安…

ubuntu+.net6+docker 应用部署教程

先期工作 1、本地首先安装 Docker Desktop 2、本地装linux in windows 3、生成镜像 后期工作 1、云服务器部署 生成镜像方法 1、生成Dockerfile配置文件 开发工具visual studio 2022 如果项目已经存在&#xff0c;可以选中项目&#xff0c;右键点击->选择添加Docker…