ArrayList与顺序表的简单理解

 前言----list

         在集合框架中,List是一个接口,继承自Collection。Collection也是一个接口,该接口中规范了后序容器中常用的一些方法,具体如下所示:

                

        Iterable也是一个接口,表示实现该接口的类是可以逐个元素进行遍历的,具体如下: 

             

        从数据结构的角度来看,List就是一个线性表,即n个具有相同类型元素的有限序列,在该序列上可以执行增删 改查以及变量等操作。 

        要知道List是个接口,并不能直接用来实例化。 如果要使用,必须去实例化List的实现类。在集合框架中,ArrayList和LinkedList都实现了List接口,具体使用参考下文。

1.线性表

        线性表(linear list)是n个具有相同特性的数据元素的有限序列

        线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列... 线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的,线性表在物理上存储时,通常以数组和链式结构的形式存储。

2.顺序表

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

3. 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 底层是一段连续的空间,并且可以动态扩容,是一个动态类型的顺序表(物理地址连续存储单元依次存储数据元素线性结构

3.1 ArrayList的构造

        1ArrayList()--->空参构造

 public static void main(String[] args) {ArrayList<Integer> arrayList = new ArrayList<>();arrayList.add(2023);arrayList.add(11);arrayList.add(28);}

        底层代码逻辑:

 

        2.2ArrayList(Collection<? extends E> c)-------->利用其他 Collection 构建 ArrayList

        <? extends E>------------------------------>
        该语句规定了ArrayList类的类型上界,即被用来存储到arraylist类中数组空间elementdata里的元素的类型上限是E,后面定义要被装载的元素类型必须是E本身或者E的子类。 

public static void main(String[] args) {ArrayList<Integer> list = new ArrayList<>();list.add(-1);list.add(100);list.add(200);ArrayList<Number> list12 = new ArrayList<>(list);list12.add(-100);System.out.println(list12);}

        代码执行结果如下图所示: 

 

        我们构造的list(1、实现了 collection接口,能够支持一些规范的容器操作;2、是支持小于等于interger类数据的存储),可以传递到list12里(1、list12实现了collection接口,2、它支持的数据类型<=number,已知interger< number)

        2.3ArrayList(int initialCapacity)----->指定顺序表初始容量

 public static void main(String[] args) {ArrayList<Integer> arrayList = new ArrayList<>(2);arrayList.add(100);arrayList.add(200);}

源码分析: 

           

 all in all:

3.2 ArrayList常见操作

        一般来说常见的方法如下图所示:

        下面来对一些较为重要的方法通过源代码来进行分析:

        1.boolean add(E e) ------>尾插 e

       

        首先arraylist的底层设置,默认容量为10;

        当我们执行完成以上代码的第一句时,虽然我们有默认为10的存储空间,但是当前却没有给顺序表list分配;当执行完第二句(即第一句add语句)时,我们才会分配一个容量为10的空间给list;

        当我们一直执行add操作,为了确保一直有存储空间来存储数据,在每一次add语句执行添加元素之前,语句会提前检查剩余的容量是否足够,当容量不足以存储数据时,会提前对空间容量进行扩容,且扩容是在前一个容量的数量上乘以1.5(即1.5倍扩容)

        具体如下图展示:

        小结:
        1. 检测是否真正需要扩容之后,最后是通过调用 grow 进行扩容
        2. 预估需要库容的大小 初步预估按照1.5 倍大小扩容
(1、初步预估按照1.5倍大小扩容 ;2、如果用户所需大小超过预估1.5倍大小,则按照用户所需大小扩容;3、 真正扩容之前检测是否能扩容成功,防止太大导致扩容失败)
        3. 也可以使调用copyOf 方法进行扩容

        2. void add(int index, E element)

        在 list 的 index 位置插入指定元素, index 及后续的元素统一往后移动一个位置,下图为底层原码:

         3.List<E> subList(int fromIndex, int toIndex) ---->

        理解:使用list中[0, 4)之间的元素构成一个新的SubList返回,但是和ArrayList共用一个elementData数组;Sub:截取产生的list,不是新产生的,而是直接将原来list相对应位置的地址传递到新的list当中。

 public static void main(String[] args) {ArrayList<Integer> arraylist = new ArrayList<>();arraylist.add(2023);arraylist.add(11);arraylist.add(28);List<Integer> sub = arraylist.subList(1, 3);System.out.println(sub);sub.set(0,100000);System.out.println(sub);System.out.println(arraylist);}

        运行结果展示: 

 

        该操作构成一个新的list返回,但是和arrayList共用一个数组,不会产生一个新的对象,所以在新list上进行修改数值时,由于指向的部分引用相同,会导致就list的数值也会发生变化。 如下下图分析所示:

 

3.3 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();
}

        关于迭代器:

4. ArrayList的优缺点

        由于其底层是一段连续空间,当在ArrayList任意位置插入或者删除元素时,就需要将后序元素整体往前或者往后搬移,时间复杂度为O(n),效率比较低,因此ArrayList不适合做任意位置插入和删除比较多的场景,下面是详细的总结:

缺点:

  1. 插入数据必须移动其他数据,最坏情况下,就是插入到0位置,时间复杂度O(N);
  2. 删除数据必须移动其他数据,最坏情况下,就是删除0位置,时间复杂度O(N)
  3. 扩容之后有可能浪费空间(扩容之后结果我们只使用一两个空间)。

优点:

  1. 在给定下标情况下进行查找的时候,时间复杂度O(1);

        注意:顺序表适合给定下标查找的情况。

ps:本次内容就到这里了,如果对你有帮助的话,还请一键三连哦!!!

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

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

相关文章

编写安全 JavaScript 代码的最佳实践

编写安全 JavaScript 代码的最佳实践 JavaScript 的动态特性使其成为事实上的浏览器语言和世界上最流行的编程语言。 JS 最受欢迎的有用功能之一是即时分析。这意味着浏览器在下载内容的同时执行代码&#xff0c;这显然有其优势。然而&#xff0c;这种程度的自由也伴随着问题…

Redis实战命令

实战命令 单值缓存 set key value get key 对象缓存 &#xff08;1&#xff09;set user:1 value(json格式) &#xff08;2&#xff09;mset user:1:name junfeng user:1:age 18 mget user:1:name user:1:age 分布式锁 分布式锁解决了什么问题&#xff1f; 分布式锁解…

[带余除法寻找公共节点]二叉树

二叉树 题目描述 如上图所示&#xff0c;由正整数1, 2, 3, ...组成了一棵无限大的二叉树。从某一个结点到根结点&#xff08;编号是1的结点&#xff09;都有一条唯一的路径&#xff0c;比如从10到根结点的路径是(10, 5, 2, 1)&#xff0c;从4到根结点的路径是(4, 2, 1)&#x…

【中间件】服务化中间件理论intro

中间件middleware 内容管理 intro服务化middleware架构注册中心intro服务治理系统intro 本文主要intro服务化中间件的探讨 去年cfeng写了一篇博客走马观花般阐述了Spring Cloud下面的各种中间件&#xff0c;连深入使用都谈不上&#xff0c;只能说intro&#xff0c;在实际work中…

linux用户身份切换su和 sudo

su 切换root&#xff0c;但是&#xff0c;环境变量是之前用户的 可以看到利用su切换&#xff0c;根目录还是pro1的 su - 连同环境一起切换成root&#xff0c;切换后工作目录都不一样了&#xff0c;看输入内容左侧信息&#xff0c;和第一个图片比较 -c仅执行一次命令&#xff0…

面试必须要知道的MySQL知识--索引

10 索引 10.1 数据页存储结构 10.1.1 数据页的各个部分 在讲索引之前&#xff0c;让我们看看一个单独的数据页是什么样子的 去除掉一些我们不太需要那么关注的部分后&#xff0c;简化如下&#xff1a; 也就是说平时我们在一个表里插入的一行一行的数据会存储在数据页里&#…

k8s-deployment控制器 5

K8s控制器是Kubernetes&#xff08;简称k8s&#xff09;系统中一个重要的组成部分&#xff0c;它是一个管理Pod的中间层&#xff0c;可以创建和管理多个Pod副本&#xff0c;确保它们按照预定的数量和行为进行运行。 通过编写yaml文件将信息全部存到etcd中&#xff0c;控制器通…

HTTP协议发展

HTTP 1.0 -> HTTP 1.1 -> HTTP 2.0 -> HTTP 3.0 (QUIC) 每一代HTTP解决了什么问题&#xff1f; 下图说明了主要功能。 HTTP 1.0 于 1996 年最终确定并完整记录。对同一服务器的每个请求都需要单独的 TCP 连接。 HTTP 1.1 于 1997 年发布。TCP 连接可以保持打开状态…

Flask教程入门

1.学习Flask之前&#xff0c;首先需要对URL进行一定的了解。 URL的一些知识&#xff1a; 1.URL只能包含ASCII码里面一些可显示的字符&#xff0c;如A-Z&#xff0c;a-z&#xff0c;0-9&#xff0c;&&#xff0c;#&#xff0c;%&#xff0c;&#xff1f;&#xff0c;/等字符…

spring boot项目未将resource目录标志为资源目录导致配置文件无效因而运行报错问题

能编译&#xff0c;但不能运行。感觉配置文件没有生效。 将程序代码发给同事&#xff0c;我自己能跑&#xff0c;他不能跑&#xff0c;提示无法构造redis对象。redis的链接写在配置文件里&#xff0c;其实是可以连接的。然后从GIT库下载代码&#xff0c;也同样不能跑。同事的操…

外网IP和内网IP的区别

首先得先知道什么是ip地址&#xff0c;它就是唯一标识连接网络的设备的&#xff0c;即IP地址充当了设备在网络中的“住址”&#xff0c;使得设备能够相互通信和交换数据。 我们常听开发人员说外网内网&#xff0c;那么它们有什么区别呢&#xff1f; 外网可以理解为互联网&…

Springboot的excel导出

这里导出excel用到的是 阿里巴巴的easyexcel 1、首先导入依赖 <!--alibaba easyexcel--><dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>2.1.6</version> </dependency> 2、…

第二十章——多线程

一.线程简介 线程的特点 1.进程是资源分配的最小单位&#xff0c;线程是最小的执行单位 2.一个进程可以有多个线程 3.线程共享进程资源 二.创建线程 1.继承Thread类 1.Thread类是java.lang包中的一个类&#xff0c;从这个类实例化的对象代表线程&#xff0c;程序员启动一个新…

三 STM32F4使用Sys_Tick 实现微秒定时器和延时

更多细节参考这篇 1. 什么是时钟以及作用 1.1 什么是时钟 时钟是由电路产生的周期性的脉冲信号&#xff0c;相当于单片机的心脏 1.2 时钟对于STM32的作用 指令同步&#xff1a;cpu和内核外设使用时钟信号来进行指令同步数据传输控制&#xff1a; 时钟信号控制数据在内部总…

sqli-labs(6)

27. 过滤了union和select 使用双写绕过 有报错信息使用报错注入 1and(extractvalue(1,concat(0x5c,database())))and11 1and(updatexml(1,concat(0x7e,database(),0x7e),1))and11 1and(extractvalue(1,concat(0x5c,(selseselectlectect(group_concat(table_name))from(inform…

Spring Boot 3 + Spring Security 6 最新版本修改 Json 登录后 RememberMe 功能问题失效的解决方案

当 Spring Boot 版本更新到 3 之后&#xff0c;最低要求的 JDK 版本变为 17&#xff0c;相应的 最新版本的 Spring Security 的配置也发生了变化&#xff0c;一下主要讲解一些新的 Spring Security 的配置方法 1. 配置由继承WebSeucrityConfigurerAdapter变成只需添加一个Secur…

每天五分钟计算机视觉:LeNet是最早用于数字识别的卷积神经网络

LeNet 假设你有一张 32321 的图片,然后使用 6 个 55的过滤器,步幅为 1,padding 为 0,输出结果为 28286。图像尺寸从 3232 缩小到 2828。 然后进行池化操作,使用平均池化,过滤器的宽度为 2,步幅为 2,图像的尺寸,高度和宽度都缩小了 2 倍,输出结果是一个14146 的图像。…

【LeetCode】挑战100天 Day13(热题+面试经典150题)

【LeetCode】挑战100天 Day13&#xff08;热题面试经典150题&#xff09; 一、LeetCode介绍二、LeetCode 热题 HOT 100-152.1 题目2.2 题解 三、面试经典 150 题-153.1 题目3.2 题解 一、LeetCode介绍 LeetCode是一个在线编程网站&#xff0c;提供各种算法和数据结构的题目&…

Redis 持久化机制

client Redis[内存] --> 内存数据、磁盘数据----> 磁盘&#xff0c;Redis官方提供了两种不同的持久化方案将内存中的数据存储在硬盘中&#xff1a; 快照&#xff08;Snapshot&#xff09; AOF只追加日志文件。 1、快照&#xff08;Snapshot&#xff09; 1、快照的特点…

鸿蒙开发报错:agconnect sdk not initialized. please call initialize()【BUG已解决】

文章目录 项目场景:问题描述原因分析:解决方案:总结:项目场景: 鸿蒙开发报错: agconnect sdk not initialized. please call initialize() 问题描述 报错内容为: 10-25 11:41:01.152 6076-16676 E A0c0d0/JSApp: app Log: 数据查询失败: {“code”:1100001,“messag…