ArrayList源码分析、扩容机制面试题,数组和List的相互转换,ArrayList与LinkedList的区别

目录

1.java集合框架体系

2. 前置知识-数组

2.1 数组

2.1.1 定义:

2.1.2 数组如何获取其他元素的地址值?(寻址公式)

2.1.3 为什么数组索引从0开始呢?从1开始不行吗?

3. ArrayList

3.1 ArrayList和和Vector的区别?(了解)

3.2 ArrayList 可以添加 null 值吗?

3.3 ArrayList源码

成员变量

​编辑构造方法

3.4 ArrayList 底层实现原理 ★

3.5 ArrayList list = new ArrayList(10)中的list扩容几次?★

3.6 数组和List之间相互转换?★

3.7 数组和List之间相互转换过程中,数据发生修改,结果会变吗(有影响吗)?★

3.7.1  用Arrays.asList() 转List后,如修改了数组内容,list集合结果受影响吗?

3.7.2 List用toArray() 转数组后,如果修改了List内容,数组受影响吗?

4. 前置知识-链表

4.1单向链表

4.1.1 单向链表特点及参考源码

4.1.2 单向链表时间复杂度分析

1 查询操作

2 插入和删除操作

4.2 双向链表

4.2.1 双向链表特点及参考源码

4.2.2 双向链表时间复杂度分析

1. 查询操作

2 增删操作

5. LinkedList

6. ArrayList与LinkedList区别?★


1.java集合框架体系

2. 前置知识-数组

2.1 数组

2.1.1 定义:

数组(Array)是一种用连续内存空间存储相同数据类型数据的线性数据结构。

int[] array = {22,33,88,66,55,25};

2.1.2 数组如何获取其他元素的地址值?(寻址公式

在数组在内存中查找元素的时候,是有一个寻址公式的,如下:
arr[i] = baseAddress + i * dataTypeSize

2.1.3 为什么数组索引从0开始呢?从1开始不行吗?

实际上并不是不行。而是如果数组索引从1开始的话,整体性能会变低。
因为寻址公式会变为a[i] = baseAddress + (i-1) *dataTypeSize,也就是说,多了一个减法操作。

3. ArrayList

ArrayList 的底层是数组队列,相当于动态数组。与 Java 中的数组相比,它的容量能动态增长。在添加大量元素前,应用程序可以使用ArrayList底层API的 ensureCapacity()操作来增加 ArrayList 实例的容量。这可以减少递增式再分配的数量。

 

3.1 ArrayList和和Vector的区别?(了解)

  • ArrayList 是 List 的主要实现类,底层使用 Object[]存储,适用于频繁的查找工作,线程不安全 。  

  • Vector 是 List 的古老实现类,底层使用Object[] 存储,线程安全。

3.2 ArrayList 可以添加 null 值吗?

可以。ArrayList 中可以存储任何类型的对象,包括 null 值。不过,不建议向ArrayList 中添加 null 值, null 值无意义,会让代码难以维护比如忘记做判空处理就会导致空指针异常。

3.3 ArrayList源码

成员变量

构造方法

第一个构造是带初始化容量的构造函数,可以按照指定的容量初始化数组
第二个是无参构造函数,默认创建一个空集合
/***构造包含指定collection元素的列表,这些元素利用该集合的迭代器按顺序返回*如果指定的集合为null,throws NullPointerException。*/
public ArrayList(Collection<? extends E> c) {elementData = c.toArray();if ((size = elementData.length) != 0) {if (elementData.getClass() != Object[].class)elementData = Arrays.copyOf(elementData, size, Object[].class);} else {// replace with empty array.this.elementData = EMPTY_ELEMENTDATA;}
}
collection 对象转换成数组,然后将数组的地址的赋给 elementData

3.4 ArrayList 底层实现原理 ★

1. 底层数据结构

ArrayList 底层是用动态的数组实现的

2. 初始容量

ArrayList 初始容量为 0 ,当第一次添加数据的时候才会初始化容量为 10

3. 扩容逻辑

ArrayList 在进行扩容的时候是原来容量的 1.5 倍,每次扩容都需要拷贝数组

4. 添加逻辑

添加数据的流程:

1. 确保数组已使用长度( size )加 1 之后足够存下下一个数据
2. 计算数组的容量,如果当前数组已使用长度 +1 后的大于当前的数组长度,
3. 则调用 grow 方法扩容(原来的 1.5 倍)
4. 确保新增的数据有地方存储之后,则将新元素添加到位于 size 的位置上。
5. 返回添加成功布尔值。

3.5 ArrayList list = new ArrayList(10)中的list扩容几次?

答:该语句只是声明和实例了一个 ArrayList ,指定了容量为 10 ,未扩容

ArrayList的扩容机制如下:

  1. ArrayList被初始化时,如果没有指定初始容量,它将使用默认的初始容量(10)。

  2. 当添加元素超过当前容量时,ArrayList会进行扩容。默认情况下,扩容后的容量是当前容量的1.5倍(即增加50%)。

3.6 数组和List之间相互转换?★

参考回答:

  • 数组转List ,使用JDKjava.util.Arrays工具类的asList方法,返回一个List集合
  • List转数组,使用ListtoArray方法。无参toArray方法返回 Object数组,传入初始化长度的数组对象,返回该对象数组

3.7 数组和List之间相互转换过程中,数据发生修改,结果会变吗(有影响吗)?★

分为两种情况:

3.7.1  用Arrays.asList() 转List后,如修改了数组内容,list集合结果受影响吗?

答:会受影响

Arrays.asList 方法返回的是一个固定大小的列表,它的底层仍然是原始数组。

当你通过 Arrays.asList 获得的列表并尝试修改其中的元素时,实际上是在修改原始数组的内容,因为列表中的元素和数组中的元素是同一个对象(同一个地址引用)。

源码如下:

3.7.2 List用toArray() 转数组后,如果修改了List内容,数组受影响吗?

答:不会影响。

list用了toArray转数组后,如果修改了list内容,数组不会影响,当调用了toArray  以后,在底层是它是进行了数组的拷贝,跟原来的元素就没啥关系了,所以即使  list修改了以后,数组

也不受影响

4. 前置知识-链表

LinkedList 底层数据结构——双向链表

4.1单向链表

4.1.1 单向链表特点及参考源码

  • 链表中的每一个元素称之为结点(Node
  • 物理存储单元上,非连续、非顺序的存储结构
  • 单向链表:每个结点包括两个部分:一个是存储数据元素的数据域,另一个 是存储下一个结点地址的指针域。记录下个结点地址的指针叫作后继指针next

代码实现参考:

4.1.2 单向链表时间复杂度分析

1 查询操作

查询:头节点:O(1),一般情况:O(n)
  • 只有在查询头节点的时候不需要遍历链表,时间复杂度是O(1)
  • 查询其他结点需要遍历链表,时间复杂度是O(n)
2 插入和删除操作

增删:头节点:O(1),一般情况:O(n)

  • 只有在添加和删除头节点的时候不需要遍历链表,时间复杂度是O(1)
  • 添加或删除其他结点需要遍历链表找到对应节点后,才能完成新增或删除节点,时间复杂度是O(n)

4.2 双向链表

4.2.1 双向链表特点及参考源码

而双向链表,顾名思义,它支持两个方向
  • 每个结点不止有一个后继指针 next 指向后面的结点
  • 有一个前驱指针 prev 指向前面的结点
代码实现参考:

4.2.2 双向链表时间复杂度分析

1. 查询操作

查询:头尾节点:O(1),一般情况:O(n),给定节点找前驱节点:O(1)

  • 查询头尾结点的时间复杂度是O(1)
  • 平均的查询时间复杂度是O(n)
  • 给定节点找前驱节点的时间复杂度为O(1)
2 增删操作
增删:头尾节点:O(1),一般情况:O(n),给定节点找前驱节点:O(1)
  • 头尾结点增删的时间复杂度为O(1)
  • 其他部分结点增删的时间复杂度是 O(n)
  • 给定节点增删的时间复杂度为O(1)

5. LinkedList

LinkedList 底层数据结构——双向链表

查询快,增删改慢,适用于读多写少的场景

6. ArrayList与LinkedList区别?★

从四个方面来谈。

  • 底层数据结构:ArrayList 是动态数组的数据结构实现,LinkedList 是双向链表的数据结构实现
  • 效率上,除了 LinkedList不支持下标查询,ArrayList支持下标查询。其他都差不多。
  • 空间上,ArrayList底层是数组,内存连续,节省内存。LinkedList 是双向链表需要存储数据,和两个指针,更占用内存。
  • 线程安全问题,ArrayList和LinkedList都不是线程安全的。

如果需要保证线程安全,有两种方案:

  • 在方法内使用,局部变量则是线程安全的
  • 使用线程安全的ArrayList和LinkedList:
Collections.synchronizedList(new ArrayList<>());
Collections.synchronizedList(new LinkedList<>());

还有一下三个方面的区别可以了解一下:

  • 插入和删除是否受元素位置的影响:
    • ArrayList 采用数组存储,所以插入和删除元素的时间复杂度受元素位置的影响。 比如:执行add(E e)方法的时候, ArrayList 会默认在将指定的元素追加到此列表的末尾,这种情况时间复杂度就是 O(1)。但是如果要在指定位置 i 插入和删除元素的话(add(int index, E element)),时间复杂度就为 O(n)。因为在进行上述操作的时候集合中第 i 和第 i 个元素之后的(n-i)个元素都要执行向后位/向前移一位的操作。
    • LinkedList 采用链表存储,所以在头尾插入或者删除元素不受元素位置的影响(add(E e)addFirst(E e)addLast(E e)removeFirst()、 removeLast()),时间复杂度为 O(1),如果是要在指定位置 i 插入和删除元素的话(add(int index, E element)remove(Object o),remove(int index)), 时间复杂度为 O(n) ,因为需要先移动到指定位置再插入和删除。
  • 是否支持快速随机访问: LinkedList 不支持高效的随机元素访问,而 ArrayList(实现了 RandomAccess 接口) 支持。快速随机访问就是通过元素的序号快速获取元素对象(对应于get(int index)方法)。
  • 内存空间占用: ArrayList 的空间浪费主要体现在在 list 列表的结尾会预留一定的容量空间,而 LinkedList 的空间花费则体现在它的每一个元素都需要消耗比 ArrayList 更多的空间(因为要存放直接后继和直接前驱以及数据)。

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

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

相关文章

地下管线三维建模,市面上有哪些软件

1. 地下管线&#xff1a;城市“生命线” 地下管线是城市的重要基础设施&#xff0c;包括供水、排水、燃气、热力、电力、通信等管线&#xff0c;它们如同城市的“生命线”&#xff0c;支撑着城市的正常运转。如果缺乏完整和准确的地下管线信息&#xff0c;施工破坏地下管线的事…

蓝桥杯刷题——day5

蓝桥杯刷题——day5 题目一题干解题思路一代码解题思路二代码 题目二题干解题思路代码 题目一 题干 给定n个整数 a1,a2,⋯ ,an&#xff0c;求它们两两相乘再相加的和&#xff0c;即&#xff1a; 示例一&#xff1a; 输入&#xff1a; 4 1 3 6 9 输出&#xff1a; 117 题目链…

L1-3流量分析

1. 初步分析 数据包下载 流量分析基础篇 使用科来网络分析系统&#xff0c;打开L1-3.pcapng数据包&#xff0c;查看数据包中ssh的协议占的比例较大。 2. 通过分析数据包L1-3&#xff0c;找出黑客的IP地址&#xff0c;并将黑客的IP地址作为FLAG(形式:[IP地址)提交; 获取的fl…

docker启动一个helloworld(公司内网服务器)

这里写目录标题 容易遇到的问题&#xff1a;1、docker连接问题 我来介绍几种启动 Docker Hello World 的方法&#xff1a; 最简单的方式&#xff1a; docker run hello-world这会自动下载并运行官方的 hello-world 镜像。 使用 Nginx 作为 Hello World&#xff1a; docker…

【网络取证篇】取证实战之PHP服务器镜像网站重构及绕密分析

【网络取证篇】取证实战之PHP服务器镜像网站重构及绕密分析 在裸聊敲诈、虚假理财诈骗案件类型中&#xff0c;犯罪分子为了能实现更低成本、更快部署应用的目的&#xff0c;其服务器架构多为常见的初始化网站架构&#xff0c;也称为站库同体服务器&#xff01;也就是说网站应用…

图像处理 - 车道线检测:智能驾驶的“眼睛”

引言 在智能驾驶技术飞速发展的今天&#xff0c;车道线检测作为一项基础而关键的技术&#xff0c;扮演着车辆“眼睛”的角色。它不仅关系到车辆的导航和定位&#xff0c;还直接影响到自动驾驶系统的安全性和可靠性。本文将带你深入了解车道线检测技术的原理、方法以及在实际应用…

【Linux学习】十五、Linux/CentOS 7 用户和组管理

Linux下组和用户的管理都必须是root用户下进行&#xff1a; 一、组的管理 1.组的创建 格式&#xff1a; groupadd 组名参数&#xff1a; -g&#xff1a;指定用户组的组ID&#xff08;GID&#xff09;&#xff0c;如果不提供则由系统自动分配。 【案例】创建一个名为 oldg…

Unity类银河战士恶魔城学习总结(P179 Enemy Archer 弓箭手)

教程源地址&#xff1a;https://www.udemy.com/course/2d-rpg-alexdev/ 本章节实现了敌人弓箭手的制作 Enemy_Archer.cs 核心功能 状态机管理敌人的行为 定义了多个状态对象&#xff08;如 idleState、moveState、attackState 等&#xff09;&#xff0c;通过状态机管理敌人的…

Pikachu靶场——XXE漏洞

XXE&#xff08;XML External Entity&#xff09;漏洞 XXE&#xff08;XML External Entity&#xff09;漏洞是一种常见的安全漏洞&#xff0c;发生在处理 XML 数据的应用程序中。当应用程序解析 XML 输入时&#xff0c;如果没有正确配置或过滤外部实体的加载&#xff0c;就可能…

使用 ESP-IDF 进行esp32-c3开发第四步:VSCode里安装ESP-IDF插件

很多小伙伴还是习惯在VSCode里写代码&#xff0c;所以今天进行了--使用 ESP-IDF 进行esp32-c3开发第四步&#xff1a;VSCode里安装ESP-IDF插件 安装和配置 首先到VSCode的插件页面&#xff0c;搜索esp&#xff0c;排名第一的就是ESP-IDF插件&#xff0c;点击安装即可。 在命令…

SSM 垃圾分类系统——高效分类的科技保障

第五章 系统功能实现 5.1管理员登录 管理员登录&#xff0c;通过填写用户名、密码、角色等信息&#xff0c;输入完成后选择登录即可进入垃圾分类系统&#xff0c;如图5-1所示。 图5-1管理员登录界面图 5.2管理员功能实现 5.2.1 用户管理 管理员对用户管理进行填写账号、姓名、…

部署GitLab服务器

文章目录 环境准备GitLab部署GitLab服务器GitLab中主要的概念客户端上传代码到gitlab服务器CI-CD概述软件程序上线流程安装Jenkins服务器 配置jenkins软件版本管理配置jenkins访问gitlab远程仓库下载到子目录部署代码到web服务器自动化部署流程 配置共享服务器配置jenkins把git…

泷羽sec学习打卡-brupsuite8伪造IP和爬虫审计

声明 学习视频来自B站UP主 泷羽sec,如涉及侵权马上删除文章 笔记的只是方便各位师傅学习知识,以下网站只涉及学习内容,其他的都 与本人无关,切莫逾越法律红线,否则后果自负 关于brupsuite的那些事儿-Brup-FaskIP 伪造IP配置环境brupsuite导入配置1、扩展中先配置python环境2、安…

如何在 Ubuntu 22.04 上使用 Fail2Ban 保护 SSH

前言 SSH&#xff0c;这玩意儿&#xff0c;简直是连接云服务器的标配。它不仅好用&#xff0c;还很灵活。新的加密技术出来&#xff0c;它也能跟着升级&#xff0c;保证核心协议的安全。但是&#xff0c;再牛的协议和软件&#xff0c;也都有可能被攻破。SSH 在网上用得这么广&…

智能家居WTR096-16S录放音芯片方案,实现语音播报提示及录音留言功能

前言&#xff1a; 在当今社会的高速运转之下&#xff0c;夜幕低垂之时&#xff0c;许多辛勤工作的父母尚未归家。对于肩负家庭责任的他们而言&#xff0c;确保孩童按时用餐与居家安全成为心头大事。此时&#xff0c;家居留言录音提示功能应运而生&#xff0c;恰似家中的一位无形…

EasyGBS国标GB28181-2016标准解读:基于TCP协议的视音频媒体传输

在探讨EasyGBS平台基于GB28181-2016标准的TCP协议视音频媒体传输时&#xff0c;我们首先需要了解GB28181标准的基本背景。GB28181&#xff0c;即GB/T28181—2016《公共安全视频监控联网系统信息传输、交换、控制技术要求》&#xff0c;是公安部提出的公共安全行业标准&#xff…

[C++]C++工具之对异常情况的处理(throw、catch、try)以及用命名空间避免同名冲突

一、C 异常处理&#x1f60a; 1.1 定义 C 中的异常处理用于应对程序运行中的异常情况&#xff08;如除零、数组越界等&#xff09;&#xff0c;通过 try-catch 机制捕获和处理错误&#xff0c;防止程序崩溃。 异常是程序运行时意外发生的事件&#xff0c;可以通过抛出&#xf…

博客MDX渲染方案

MDX渲染方案 Link 本文不由AI生成,原创,转载请注明 当个人博客网站或是独立网站有博客页时,通过渲染mdx文件是一种效率比较高的方式生成博客文章的一种方式 MDX渲染方案 我之前是通过typora直接导出html文件,这种纯静态页面 缺点:太繁琐优点:可以自己选不同的主题,成本…

VScode MAC按任意键关闭终端 想要访问桌面文件

说明 最近配置MAC上CPP的运行环境&#xff0c;在安装必要的CPP插件后&#xff0c;配置launch和task等json文件后&#xff0c;点击运行三角形&#xff0c;每次都会跳出main想要访问桌面上的文件。并且输出也是在调试控制台&#xff0c;非常逆天。 尝试 尝试1:尽管我尝试将ta…

注意力机制+时空特征融合!组合模型集成学习预测!LSTM-Attention-Adaboost多变量时序预测

注意力机制时空特征融合&#xff01;组合模型集成学习预测&#xff01;LSTM-Attention-Adaboost多变量时序预测 目录 注意力机制时空特征融合&#xff01;组合模型集成学习预测&#xff01;LSTM-Attention-Adaboost多变量时序预测效果一览基本介绍程序设计参考资料 效果一览 基…