Java进阶(List)——面试时List常见问题解读 结合源码分析

前言
List、Set、HashMap作为Java中常用的集合,需要深入认识其原理和特性。
本篇博客介绍常见的关于Java中List集合的面试问题,结合源码分析题目背后的知识点。
关于的Set的博客文章如下:
- Java进阶(Set)——面试时Set常见问题解读 & 结合源码分析
关于HaseMap的博客文章如下:
- Java进阶(HashMap)——面试时HashMap常见问题解读 & 结合源码分析
- Java进阶(ConcurrentHashMap)——面试时ConcurrentHashMap常见问题解读 & 结合源码分析 & 多线程CAS比较并交换 初识
其他相关的List的文章合集如下:
-
手动实现ArrayList & 源码的初步理解分析 & 数组插入数据和删除数据的问题
-
Java学数据结构(1)——抽象数据类型ADT & 表List、栈Stack和队列Qeue
目录
- 前言
- 引出
- ArrayList 如何扩容的?/ArrayList的大小是如何自动增加的?
- 1.add添加第一个元素
- 2.添加第11个元素时
- 如何复制某个ArrayList到另一个Arraylist中去?
- 厘清概念:深浅拷贝
- 复制的方法
- 在索引中ArrayList的增加或者删除某个对象的运行过程?效率很低吗?解释一下为什么?
- 效率确实低
- 源码arraycopy方法
- 现在我有一个很大的数组需要拷贝,原数组大小是 5k,请问如何快速拷贝?
- 如何获得一个线程安全的ArrayList集合?
- Collections.synchronizedList
- 源码分析
- LinkedList 和 ArrayList 该如何选择?
- 选择原则
- LinkedList源码node节点
- Vector 集合
- 总结
引出
1.ArrayList如何扩容,1.5倍;
2.ArrayList如何拷贝,深拷贝,浅拷贝;
3.ArrayList的增加或者删除效率低,arraycopy方法;
4.指定长度创建ArrayList对象,避免频繁扩容;
5.线程安全的ArrayList集合:Collections.synchronizedList;
6.LinkedList 和 ArrayList 该如何选择:ArrayList增删效率低,查询效率高;LinkedList 查询效率低,增删效率高
7.Vector 集合和 ArrayList 区别:Vector扩容机制为原始的2倍,线程安全;
ArrayList 如何扩容的?/ArrayList的大小是如何自动增加的?
ArrayList初始化的时候,若没有给定长度,则默认调用无参构造

此处elelmentData为ArrayList底层数组,后面DEFAULTCAPACITY_EMPTY_ELEMENTDATA 为常量数组初值为空,即长度为0

1.add添加第一个元素
当执行add方法添加第一个元素时,执行下面的代码

此处涉及到两条代码:
- ensureCapacityInternal方法内会调用calculateCapacity方法,此处才是赋予数组长度为10
ensureCapacityInternal 方法

calculateCapacity方法

private static int calculateCapacity(Object[] elementData, int minCapacity) {//如果数组是空的if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {//返回数组的容量,DEFAULT_CAPACITY=10return Math.max(DEFAULT_CAPACITY, minCapacity);}return minCapacity;}
此时集合可以添加默认的10个元素
2.添加第11个元素时
当添加第11个元素时,ensureExplicitCapacity方法中,minCapacity为11,而原数组长度为10,所以if结构进入grow方法-扩容核心方法
ensureExplicitCapacity方法

grow方法-扩容核心方法

private void grow(int minCapacity) {// overflow-conscious code//把旧的长度赋值给oldCapacityint oldCapacity = elementData.length;//新的长度就=旧的长度*1.5int newCapacity = oldCapacity + (oldCapacity >> 1);if (newCapacity - minCapacity < 0)newCapacity = minCapacity;if (newCapacity - MAX_ARRAY_SIZE > 0)newCapacity = hugeCapacity(minCapacity);// minCapacity is usually close to size, so this is a win://按照新的长度复制出一个新的数组elementData = Arrays.copyOf(elementData, newCapacity);}
-
oldCapacity赋值为原数组长度,为10 ,newCapacity赋值为原长度1.5倍,即15
-
调用复制数组方法,将之前的数组复制到新的数组中,并将需要添加的元素加到数组最后一位,完成扩容!
如何复制某个ArrayList到另一个Arraylist中去?
重写clone方法,ArrayList克隆

厘清概念:深浅拷贝
Java进阶(4)——结合类加载JVM的过程理解创建对象的几种方式:new,反射Class,克隆clone(拷贝),序列化反序列化

浅拷贝:虽然返回一个元素一样的ArrayList,复制的是元素的引用,即其中一个改变了元素,另一个也会跟着改变
两个集合中间存储了同一份元素的引用
例如:
深拷贝:重写clone方法,利用迭代器iterator或遍历集合,重新创建引用对象,逐个添加
例如:

复制的方法

list.clone()

clone.addALl(list);

Collections.copy(clone,list);

在索引中ArrayList的增加或者删除某个对象的运行过程?效率很低吗?解释一下为什么?
效率确实低
效率是很低的,因为ArrayList无论是增加或者删除某个对象,我们都要通过对数组中的元素进行移位来实现。
- 增加元素时,我们要把要增加位置及以后的所有元素都往后移一位,先腾出一个空间,然后再进行添加。
- 删除某个元素时,我们也要把删除位置以后的元素全部元素往前挪一位,通过覆盖的方式来删除。
而这种移位就需要不断的arraycopy,是很耗时间的,所以效率自然也很低。
源码arraycopy方法
增加元素时

删除元素时

现在我有一个很大的数组需要拷贝,原数组大小是 5k,请问如何快速拷贝?
指定长度创建ArrayList对象,避免频繁扩容
如何获得一个线程安全的ArrayList集合?
Collections.synchronizedList
List<Object> datas = Collections.synchronizedList(new ArrayList<>());
源码分析

从源码可以看到集合操作都加了synchronized 关键字,保证了在同一时刻,数组和链表只会被一个线程所修改。
LinkedList 和 ArrayList 该如何选择?
选择原则
- ArrayList 底层为数组,在增加和删除元素时会频繁的调用arraycopy,所以查询效率高,增删效率低
- LinkedList 底层为链表,故查询效率低,但增删效率高。
LinkedList源码node节点

- item 为当前元素
- next指向下一个元素,若为最后一个则为null
- prev指向上一个元素,若为第一个则为null

Vector 集合
- vector 和 ArrayList 基本一样
- 区别在于 vector扩容机制为原始的2倍,ArrayList为之前的1.5倍
- vector 是线程安全的,ArrayList是非线程安全的

总结
1.ArrayList如何扩容,1.5倍;
2.ArrayList如何拷贝,深拷贝,浅拷贝;
3.ArrayList的增加或者删除效率低,arraycopy方法;
4.指定长度创建ArrayList对象,避免频繁扩容;
5.线程安全的ArrayList集合:Collections.synchronizedList;
6.LinkedList 和 ArrayList 该如何选择:ArrayList增删效率低,查询效率高;LinkedList 查询效率低,增删效率高
7.Vector 集合和 ArrayList 区别:Vector扩容机制为原始的2倍,线程安全;
相关文章:
Java进阶(List)——面试时List常见问题解读 结合源码分析
前言 List、Set、HashMap作为Java中常用的集合,需要深入认识其原理和特性。 本篇博客介绍常见的关于Java中List集合的面试问题,结合源码分析题目背后的知识点。 关于的Set的博客文章如下: Java进阶(Set)——面试时…...
0基础学习PyFlink——个数滑动窗口(Sliding Count Windows)
大纲 滑动(Sliding)和滚动(Tumbling)的区别样例窗口为2,滑动距离为1窗口为3,滑动距离为1窗口为3,滑动距离为2窗口为3,滑动距离为3 完整代码参考资料 在 《0基础学习PyFlink——个数…...
vue3+ts 提取公共方法
因为好多页面都会使用到这个效验规则,封装一个校检规则,方便维护 封装前 封装后...
C++ ->
C -> 是访问类或结构体对象的成员的运算符 注意这里不是直接的访问.是用于访问指向对象的指针的成员 下面的代码可以很好的理解如下: #include<iostream>using namespace std;class Func{public:int i,j;void myFunc(){cout<<"i"<&l…...
VR全景在医院的应用:缓和医患矛盾、提升医院形象
医患关系一直以来都是较为激烈的,包括制度的不完善、医疗资源紧张等问题也时有存在,为了缓解医患矛盾,不仅要提升患者以及家属对于医院的认知,还需要完善医疗制度,提高医疗资源的配置效率,提高服务质量。 因…...
【python基础】format格式化函数的使用
文章目录 前言一、format()内容匹配替换1、序号索引2、关键字3、列表索引4、字典索引5、通过类的属性6、通过魔法参数 二、format()数字格式化 前言 语法:str.format() 说明:一种格式化字符串的函数。 一、format()内容匹配替换 1、序号索引 在没有参…...
Java web(三):Http、Tomcat、Servlet
文章目录 一、Java web技术栈二、Http1.1 Http请求数据格式1.2 Http响应数据格式1.3 状态码 二、Tomcat2.1 介绍2.2 web项目结构2.3 IDEA中使用Tomcat 三、Servlet3.1 Servlet使用3.2 Servlet生命周期3.3 Servlet方法和体系结构3.4 urlPattern配置 四、Request4.1 获取请求数据…...
Java实现Hive UDF详细步骤 (Hive 3.x版本,IDEA开发)
这里写目录标题 前言1. 新建项目2.配置maven依赖3.编写代码4.打jar包5.上传服务器6.代码中引用 前言 老版本编写UDF时,需要继承 org.apache.hadoop.hive.ql.exec.UDF类,然后直接实现evaluate()方法即可。 由于公司hive版本比较高(3.x&#x…...
Vue进阶(幺陆肆)Apache的Access.log分析总结
文章目录 一、前言二、常用指令 一、前言 前端项目排错阶段,可借助apache的Access.log进行请求日志查看。 二、常用指令 #查看80端口的tcp连接 #netstat -tan | grep "ESTABLISHED" | grep ":80" | wc -l #当前WEB服务器中联接次数最多的ip地…...
Apple 苹果发布 M3、M3 Pro 和 M3 Max 芯片
本心、输入输出、结果 文章目录 Apple 苹果发布 M3、M3 Pro 和 M3 Max 芯片前言M3、M3 Pro 和 M3 Max 芯片的性能相关资料图M3 Pro规格M3 Max规格弘扬爱国精神 Apple 苹果发布 M3、M3 Pro 和 M3 Max 芯片 编辑:简简单单 Online zuozuo 地址:https://blog…...
Linux常用命令及主流服务部署大全
目录 Linux 系统目录 一、常用操作命令 1、目录操作 2、文件内容操作(查看日志,更改配置文件) 3、压缩和解压缩 4、更改文件权限 二、各服务部署命令 1、增加虚拟内存 2、JDK 2.1 删除系统自带的openjdk 2.2 安装jdk 2.3 删除jd…...
list-watch集群调度
调度约束 Kubernetes 是通过 List-Watch **** 的机制进行每个组件的协作,保持数据同步的,每个组件之间的设计实现了解耦。 用户是通过 kubectl 根据配置文件,向 APIServer 发送命令,在 Node 节点上面建立 Pod 和 Container。…...
深度强化学习中的神经网络部分的作用是什么?一般如何选择合适的神经网络呢?
在深度强化学习中,神经网络部分通常用于实现值函数近似或策略近似,以帮助智能体学习如何在一个环境中做出决策以获得最大的累积奖励。这些神经网络在深度强化学习中扮演着重要的角色,具体作用如下: 1.值函数近似(Valu…...
若依系统的数据导入功能设置
一、后端 Log(title "公交站牌", businessType BusinessType.IMPORT)PreAuthorize("ss.hasPermi(busStop:busStop:import)")PostMapping("/importData")public AjaxResult importData(MultipartFile file, boolean updateSupport) throws Exce…...
vue页面父组件与子组件相互调用方法和传递参数值
vue页面父组件与子组件相互调用方法和传递参数值 父组件页面定义 <el-button type"text" icon"el-icon-refresh" click"refreshClick" slot"label"></el-button> <leftList leftClick"loadModelClick" r…...
vim使用
概述 vi(visual editor)是Unix/Linux编辑器的一种。类似于win中notepad。vim(vi improved)加强版 安装vim: $ yum install vim -y四种模式 命令模式:快速进行复制、粘贴、删除等操作,还可以…...
人工智能基础_机器学习014_BGD批量梯度下降公式更新_进一步推导_SGD随机梯度下降和MBGD小批量梯度下降公式进一步推导---人工智能工作笔记0054
然后我们先来看BGD批量梯度下降,可以看到这里,其实这个公式来源于 梯度下降的公式对吧,其实就是对原始梯度下降公式求偏导以后的梯度下降公式,然后 使用所有样本进行梯度下降得来的,可以看到* 1/n 其实就是求了一个平均数对吧.所有样本的平均数. 然后我们看,我们这里* 1/n那么…...
Android STR研究之一
简介: 先上一段谷歌的介绍 谷歌的网站地址: 电源管理 | Android 开源项目 | Android Open Source Project (google.cn) 术语 STR: STR(Suspend To RAM)的意思是“挂起到内存”,它是一种瞬间开机技术(On Now)。 当系统进入“挂起”状态…...
单链表的详解实现
单链表 结构 单链表结构中有两个数据,一个是存储数据的,还有一个指针指向下一个节点。 该图就是一个简单单链表的结构图。 接口实现 SLNode* CreateNode(SLNDataType x);//申请节点 void SLTprint(SLNode* head);//打印链表 void SLTPushBack(SLNode*…...
抛弃 scp 改用 rsync,让 Linux 下文件传输高效无比
我们都使用过 scp 来传输文件。当传输在中途或甚至在 99% 时被中断时,(每当我想起99%的中断传输时,我的心都很痛);让我们看看如何使用 rsync 来替代 scp,避免这样的不幸。 什么是rsync? Rsync…...
Linux链表操作全解析
Linux C语言链表深度解析与实战技巧 一、链表基础概念与内核链表优势1.1 为什么使用链表?1.2 Linux 内核链表与用户态链表的区别 二、内核链表结构与宏解析常用宏/函数 三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势5.1 插入效率5.2 安全…...
解决Ubuntu22.04 VMware失败的问题 ubuntu入门之二十八
现象1 打开VMware失败 Ubuntu升级之后打开VMware上报需要安装vmmon和vmnet,点击确认后如下提示 最终上报fail 解决方法 内核升级导致,需要在新内核下重新下载编译安装 查看版本 $ vmware -v VMware Workstation 17.5.1 build-23298084$ lsb_release…...
FastAPI 教程:从入门到实践
FastAPI 是一个现代、快速(高性能)的 Web 框架,用于构建 API,支持 Python 3.6。它基于标准 Python 类型提示,易于学习且功能强大。以下是一个完整的 FastAPI 入门教程,涵盖从环境搭建到创建并运行一个简单的…...
leetcodeSQL解题:3564. 季节性销售分析
leetcodeSQL解题:3564. 季节性销售分析 题目: 表:sales ---------------------- | Column Name | Type | ---------------------- | sale_id | int | | product_id | int | | sale_date | date | | quantity | int | | price | decimal | -…...
【碎碎念】宝可梦 Mesh GO : 基于MESH网络的口袋妖怪 宝可梦GO游戏自组网系统
目录 游戏说明《宝可梦 Mesh GO》 —— 局域宝可梦探索Pokmon GO 类游戏核心理念应用场景Mesh 特性 宝可梦玩法融合设计游戏构想要素1. 地图探索(基于物理空间 广播范围)2. 野生宝可梦生成与广播3. 对战系统4. 道具与通信5. 延伸玩法 安全性设计 技术选…...
使用 SymPy 进行向量和矩阵的高级操作
在科学计算和工程领域,向量和矩阵操作是解决问题的核心技能之一。Python 的 SymPy 库提供了强大的符号计算功能,能够高效地处理向量和矩阵的各种操作。本文将深入探讨如何使用 SymPy 进行向量和矩阵的创建、合并以及维度拓展等操作,并通过具体…...
听写流程自动化实践,轻量级教育辅助
随着智能教育工具的发展,越来越多的传统学习方式正在被数字化、自动化所优化。听写作为语文、英语等学科中重要的基础训练形式,也迎来了更高效的解决方案。 这是一款轻量但功能强大的听写辅助工具。它是基于本地词库与可选在线语音引擎构建,…...
现有的 Redis 分布式锁库(如 Redisson)提供了哪些便利?
现有的 Redis 分布式锁库(如 Redisson)相比于开发者自己基于 Redis 命令(如 SETNX, EXPIRE, DEL)手动实现分布式锁,提供了巨大的便利性和健壮性。主要体现在以下几个方面: 原子性保证 (Atomicity)ÿ…...
DingDing机器人群消息推送
文章目录 1 新建机器人2 API文档说明3 代码编写 1 新建机器人 点击群设置 下滑到群管理的机器人,点击进入 添加机器人 选择自定义Webhook服务 点击添加 设置安全设置,详见说明文档 成功后,记录Webhook 2 API文档说明 点击设置说明 查看自…...
接口自动化测试:HttpRunner基础
相关文档 HttpRunner V3.x中文文档 HttpRunner 用户指南 使用HttpRunner 3.x实现接口自动化测试 HttpRunner介绍 HttpRunner 是一个开源的 API 测试工具,支持 HTTP(S)/HTTP2/WebSocket/RPC 等网络协议,涵盖接口测试、性能测试、数字体验监测等测试类型…...
