数据结构 | (二) List

什么是 List
在集合框架中, List 是一个接口,继承自 Collection
Collection 也是一个接口 ,该接口中规范了后序容器中常用的一些方法,具体如下所示:
Iterable 也是一个接口,表示实现该接口的类是可以逐个元素进行遍历的,具体如下:
站在数据结构的角度来看, List 就是一个线性表,即 n 个具有相同类型元素的有限序列,在该序列上可以执行增删 改查以及变量等操作
常见接口介绍
List 中提供了好的方法,具体如下:
虽然方法比较多,但是常用方法如下:
方法解释
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 的下标
List<E> subList(int fromIndex, int toIndex)截取部分 list
List的使用
注意: List 是个接口,并不能直接用来实例化
如果要使用,必须去实例化 List 的实现类。在集合框架中, ArrayList LinkedList 都实现了 List 接口
线性表
线性表(linear list)是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结 构,常见的线性表:顺序表、链表、栈、队列...
线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的,线性表在物 理上存储时,通常以数组和链式结构的形式存储。
顺序表
顺序表是用一段 物理地址连续 的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储。在数组上完成 数据的增删查改。
ArrayList 简介
在集合框架中, ArrayList 是一个普通的类,实现了 List 接口,具体框架图如下:
说明
  1. ArrayList是以泛型方式实现的,使用时必须要先实例化
  2. ArrayList实现了RandomAccess接口,表明ArrayList支持随机访问
  3.  ArrayList实现了Cloneable接口,表明ArrayList是可以clone
  4. ArrayList实现了Serializable接口,表明ArrayList是支持序列化的
  5. Vector不同,ArrayList不是线程安全的,在单线程下可以使用,在多线程中可以选择Vector或者 CopyOnWriteArrayList
  6. ArrayList底层是一段连续的空间,并且可以动态扩容,是一个动态类型的顺序表
ArrayList 使用
ArrayList 的构造
方法解释
ArrayList()无参构造
ArrayList(Collection<? extends E> c)利用其他 Collection 构建 ArrayList
ArrayList(int initialCapacity)指定顺序表初始容量

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 常见操作
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 contains(Object o)判断 o 是否在线性表中
int indexOf(Object o)返回第一个 o 所在下标
int lastIndexOf(Object o)返回最后一个 o 的下标
List<E> subList(int fromIndex, int toIndex)截取部分 list
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());
}
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 的扩容机制
ArrayList 是一个动态类型的顺序表,即:在插入元素的过程中会自动扩容。以下是 ArrayList 中扩容方式:
  1. 检测是否真正需要扩容,如果是调用grow准备扩容
  2. 预估需要库容的大小
            初步预估按照1.5倍大小扩容
            如果用户所需大小超过预估1.5倍大小,则按照用户所需大小扩容
            
    真正扩容之前检测是否能扩容成功,防止太大导致扩容失败
  3. 使用copyOf进行扩容
ArrayList 的问题及思考
  1. ArrayList底层使用连续的空间,任意位置插入或删除元素时,需要将该位置后序元素整体往前或者往后搬移,故时间复杂度为O(N)
  2. 增容需要申请新空间,拷贝数据,释放旧空间。会有不小的消耗。
  3. 增容一般是呈2倍的增长,势必会有一定的空间浪费。例如当前容量为100,满了以后增容到200,我们再继续插入了5个数据,后面没有数据插入了,那么就浪费了95个数据空间

ArrayList的缺陷

由于ArrayList是通过数组来实现的其底层是一段连续空间,当 ArrayList 任意位置插入或者删除元素时,就需要将后序元素整体往前或者往后 搬移,时间复杂度为 O(n) ,效率比较低,因此 ArrayList 不适合做任意位置插入和删除比较多的场景 。因此: java 集合中又引入了LinkedList ,即链表结构。
链表的概念及结构
链表是一种 物理存储结构上非连续 存储结构,数据元素的 逻辑顺序 是通过链表中的 引用链接 次序实现的 。
LinkedList
LinkedList 的底层是双向链表结构 ,由于链表没有将元素存储在连续的空间中,元素存储在单独的节点中,然后通过引用将节点连接起来了,因此在在任意位置插入或者删除元素时,不需要搬移元素,效率比较高。
在集合框架中, LinkedList 也实现了 List 接口,具体如下:
【说明】
  • LinkedList实现了List接口
  • LinkedList的底层使用了双向链表
  • LinkedList没有实现RandomAccess接口,因此LinkedList不支持随机访问
  • LinkedList的任意位置插入和删除元素时效率比较高,时间复杂度为O(1)
  • LinkedList比较适合任意位置插入的场景
LinkedList 的使用
方法解释
LinkedList()无参构造
public LinkedList(Collection<? extends E> c)使用其他集合容器中元素构造List
public static void main(String[] args) {// 构造一个空的LinkedListList<Integer> list1 = new LinkedList<>();List<String> list2 = new java.util.ArrayList<>();list2.add("JavaSE");list2.add("JavaWeb");list2.add("JavaEE");// 使用ArrayList构造LinkedListList<String> list3 = new LinkedList<>(list2);
}
LinkedList 的其他常用方法介绍
方法解释
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 的下标
List<E> subList(int fromIndex, int toIndex)截取部分 list

public static void main(String[] args) {LinkedList<Integer> list = new LinkedList<>();list.add(1); // add(elem): 表示尾插list.add(2);list.add(3);list.add(4);list.add(5);list.add(6);list.add(7);System.out.println(list.size());System.out.println(list);// 在起始位置插入0list.add(0, 0); // add(index, elem): 在index位置插入元素elemSystem.out.println(list);list.remove(); // remove(): 删除第一个元素,内部调用的是removeFirst()list.removeFirst(); // removeFirst(): 删除第一个元素list.removeLast(); // removeLast(): 删除最后元素list.remove(1); // remove(index): 删除index位置的元素System.out.println(list);// contains(elem): 检测elem元素是否存在,如果存在返回true,否则返回falseif(!list.contains(1)){list.add(0, 1);}list.add(1);System.out.println(list);System.out.println(list.indexOf(1)); // indexOf(elem): 从前往后找到第一个elem的位置System.out.println(list.lastIndexOf(1)); // lastIndexOf(elem): 从后往前找第一个1的位置int elem = list.get(0); // get(index): 获取指定位置元素list.set(0, 100); // set(index, elem): 将index位置的元素设置为elemSystem.out.println(list);// subList(from, to): 用list中[from, to)之间的元素构造一个新的LinkedList返回List<Integer> copy = list.subList(0, 3); System.out.println(list);System.out.println(copy);list.clear(); // 将list中元素清空System.out.println(list.size());
}
LinkedList 的遍历
public static void main(String[] args) {LinkedList<Integer> list = new LinkedList<>();list.add(1); // add(elem): 表示尾插list.add(2);list.add(3);list.add(4);list.add(5);list.add(6);list.add(7);System.out.println(list.size());// foreach遍历for (int e:list) {System.out.print(e + " ");}System.out.println();// 使用迭代器遍历---正向遍历ListIterator<Integer> it = list.listIterator();while(it.hasNext()){System.out.print(it.next()+ " ");}System.out.println();// 使用反向迭代器---反向遍历ListIterator<Integer> rit = list.listIterator(list.size());while (rit.hasPrevious()){System.out.print(rit.previous() +" ");}System.out.println();
}
ArrayList LinkedList 的区别
不同点ArrayListLinkedList
存储空间上物理上一定连续逻辑上连续,但物理上不一定连续
随机访问支持O(1)不支持:O(N)
头插需要搬移元素,效率低O(N)只需修改引用的指向,时间复杂度为O(1)
插入空间不够时需要扩容没有容量的概念
应用场景元素高效存储+频繁访问任意位置插入和删除频繁

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

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

相关文章

分享几个通用个人简历模板|行业通用

Home(https://cvjury.com/) 专业设计的简历模板。 在竞争激烈的就业市场中脱颖而出的有效策略。 侧重于向招聘人员传达独特的价值主张。 帮助创建引人注目的简历、求职信和LinkedIn资料。 面向毕业生和学生的个性化简历解决方案。 添加图片注释&#xff0c;不超过 140 字&…

归并排序及其非递归实现

个人主页&#xff1a;Lei宝啊 愿所有美好如期而遇 目录 归并排序递归实现 归并排序非递归实现 归并排序递归实现 图示&#xff1a; 代码&#xff1a; 先分再归并&#xff0c;像是后序一般。 //归并排序 void MergeSort(int* arr, int left, int right) {int* temp (int…

MySQL——五、库表操作(上篇)

MySQL 表的基本操作一、创建表二、数据类型三、查看表四、删除表五、修改表的结构六、复制表的结构七、表的约束八、数据库字典九、存储引擎十、表物理存储结构 表的基本操作 一、创建表 数据表的每行称为一条记录&#xff08;record&#xff09;&#xff1b;每一列称为一个字…

PUPANVR-UI主菜单及设置窗体框架(9)

PUPA NVR UI主菜单及设置窗体框架 在设计UI时&#xff0c;竟量把数据、控制、显示&#xff0c;分开&#xff0c;即MVC的一个模式吧&#xff01;使用MVC这样的模式思想&#xff0c;会让代码简洁不少&#xff0c;逻辑也很清析&#xff01; 具体的代码见&#xff1a; PUPANVR这个…

第三次作业

自己实现扫描全盘的函数 def scan_disk(dir): global count,dir_count if os.path.isdir(dir): files os.listdir(dir) for file in files: print(file) dir_count 1 if os.path.isdir(dir os.sep file): …

等精度频率计verilog,quartus仿真视频,原理图,代码

名称&#xff1a;等精度频率计设计verilog quartus仿真 软件&#xff1a;Quartus 语言&#xff1a;Verilog 要求&#xff1a; A&#xff1a;测量范围信号:方波 频率:100Hz~1MHz; B&#xff1a;测试误差:<0.1%(全量程) C&#xff1a;时钟频率:50kHz D&#xff1a;预闸…

php实战案例记录(19)对登录角色的权限进行判断

在 PHP 中&#xff0c;通过以下步骤对登录角色的权限进行判断&#xff1a; 确定登录用户的角色&#xff1a;首先&#xff0c;需要确保登录用户分配了一个角色。这可以通过检查用户登录凭据&#xff08;如用户名和密码&#xff09;来验证&#xff0c;并将用户与特定角色关联起来…

(2021|NIPS,VQ-VAE,精度瓶颈松弛,三明治层归一化,CapLoss)CogView:通过转换器掌握文本到图像的生成

CogView: Mastering Text-to-Image Generation via Transformers 公众号&#xff1a;EDPJ&#xff08;添加 VX&#xff1a;CV_EDPJ 或直接进 Q 交流群&#xff1a;922230617 获取资料&#xff09; 0. 摘要 通用领域中的文本到图像生成长期以来一直是一个悬而未决的问题&#…

【算法与数据结构】--目录

第一部分&#xff1a;算法基础 第一章&#xff1a;算法入门第二章&#xff1a;数据结构概述第三章&#xff1a;算法设计与分析 3.1 贪心算法3.2 动态规划3.3 分治算法3.4 回溯算法 第二部分&#xff1a;常见数据结构 第四章&#xff1a;数组和链表 4.1 数组4.2 链表4.3 比较…

<HarmonyOS第一课>运行Hello World——闯关习题及答案

判断题 1.DevEco Studio是开发HarmonyOS应用的一站式集成开发环境。&#xff08; 对 &#xff09; 2.main_pages.json存放页面page路径配置信息。&#xff08; 对 &#xff09; 单选题 1.在stage模型中&#xff0c;下列配置文件属于AppScope文件夹的是&#xff1f;&#xff…

十、pygame小游戏开发

目录 一、安装pygame二、pygame快速入门2.1 坐标系认识2.2 创建游戏主窗口2.3 实现图像绘制2.4 游戏循环和游戏时钟2.5 简单动画实现的实现2.6 监听事件2.7 精灵和精灵组三、游戏框架搭建3.1 实现飞机大战主游戏类3.2 完成游戏初始化部分3.3 使用常量代替固定的数值3.4 完成游戏…

vba智能办公

VBA是Visual Basic for Applications的缩写&#xff0c;是一种用于Microsoft Office应用程序的编程语言。它提供了许多方便的工具和功能&#xff0c;可以帮助我们自动化任务、增强数据处理和分析能力、提高工作效率等等。在这篇文章中&#xff0c;我们将探讨一些VBA的好处。 自…

2023年DDoS攻击发展趋势的分析和推断

DDoS是一种非常“古老”的网络攻击技术&#xff0c;随着近年来地缘政治冲突对数字经济格局的影响&#xff0c;DDoS攻击数量不断创下新高&#xff0c;其攻击的规模也越来越大。日前&#xff0c;安全网站Latest Hacking News根据DDoS攻击防护服务商Link11的统计数据&#xff0c;对…

Java代码hello word

一、安装java环境 开始学习java之前&#xff0c;我们的第一步就是安装java环境&#xff0c;即常说的JDK和JRE&#xff0c;此处就不在详细介绍配置环境过程&#xff0c;可以到网上搜索java开发环境配置。 二、编写第一个程序 工具&#xff1a; 常用的java编写工具有IDE、Notep…

LeetCode——动态规划(四)

刷题顺序及思路来源于代码随想录&#xff0c;网站地址&#xff1a;https://programmercarl.com 目录 322. 零钱兑换 - 力扣&#xff08;LeetCode&#xff09; 279. 完全平方数 - 力扣&#xff08;LeetCode&#xff09; 139. 单词拆分 - 力扣&#xff08;LeetCode&#xff…

【算法与数据结构】--前言

欢迎来到《算法与数据结构》专栏&#xff01;这个专栏将引领您进入计算机科学领域中最重要、最精彩的领域之一&#xff1a;算法与数据结构。不管您是一名初学者&#xff0c;还是已经拥有一定编程经验的开发者&#xff0c;都可以从这里找到有益的知识和实践。 在计算机科学的世…

机器学习:随机森林

集成学习 集成学习&#xff08;Ensemble Learning&#xff09;是一种机器学习方法&#xff0c;通过将多个基本学习算法的预测结果进行组合&#xff0c;以获得更好的预测性能。集成学习的基本思想是通过结合多个弱分类器或回归器的预测结果&#xff0c;来构建一个更强大的集成模…

一、综合——法律法规

文章目录 一、《中华人民共和国电信条例》1.1 《电信条例》关于电信市场的规定1.2 《电信条例》关于电信服务的规定1.3 《电信条例》关于电信建设的规定二、《公用电信网间互联管理规定》2.1《网间互联规定》概述2.2 电信业务经营者的互联义务三、《中华人民共和国网络安全法》…

Window Anaconda 安装pytorch 启用cuda 终究手段

1.首先你的电脑要有NVIDIA 的显卡.没有就走吧,你如果不是window &#xff0c;也走吧&#xff0c;不一定教程管用。 2.然后要明白&#xff0c;有两种CUDA版本&#xff0c;一个叫运行时api&#xff0c;一个是驱动api 2.1 运行时cuda 版本查看 &#xff08;是你跑深度学习模型或其…

Android用户登录与数据存储:从权限请求到内外部存储的完整实践【完整实践步骤、外部存储、内部存储】

步骤 1: 登录页面布局 在 MainActivity 中实现用户登录功能&#xff0c;首先创建一个布局文件 activity_main.xml 包含用户名和密码的输入字段以及登录按钮。 <!-- activity_main.xml --> <LinearLayoutxmlns:android"http://schemas.android.com/apk/res/andr…