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=10
           return 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
        //把旧的长度赋值给oldCapacity
       int oldCapacity = elementData.length;
        //新的长度就=旧的长度*1.5
       int 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 集合

  1. vector 和 ArrayList 基本一样
  2. 区别在于 vector扩容机制为原始的2倍,ArrayList为之前的1.5倍
  3. 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倍,线程安全;

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

9.Vue前端使用iframe集成帆软报表的单点登录

一、背景 需要把帆软报表内嵌到若依里面来。 二、帆软设置 2.1 帆软报表的url 打开帆软后端里面的【目录管理】查看具体报表的url 帆软报表的具体地址为: Frm聚合报表地址: 【帆软的服务http】+【/webroot/decision/view/form?viewlet=demo/demo.frm】 CPT普通报表的地…

【腾讯云 HAI域探秘】使用Stable Diffusion大模型生成惊世骇俗的图片!

文章目录 前言环境准备高性能应用服务 HAI资格申请购买HAI高性能服务 生成图片界面汉化&#xff1a;输入提示词生成图片参数列表&#xff1a;根据提示词生成图片 总结&#xff1a;优点&#xff1a;缺点&#xff1a; 前言 AI绘画工具的发展历史可以追溯到2014年&#xff0c;当时…

SQL INNER JOIN 关键字(内部连接)

SQL INNER JOIN 关键字&#xff08;内部连接&#xff09; 内部链接INNER JOIN关键字选择两个表中具有匹配值的记录。 SQL INNER JOIN 语法 SELECT column_name(s) FROM table1 INNER JOIN table2 ON table1.column_name table2.column_name; 注释&#xff1a;INNER JOIN 与 …

4.多层感知机-3GPT版

#pic_center R 1 R_1 R1​ R 2 R^2 R2 目录 知识框架No.1 多层感知机一、感知机1、感知机2、训练感知机3、图形解释4、收敛定理5、XOR问题6、总结 二、多层感知机1、XOR2、单隐藏层3、单隐藏层-单分类4、为什么需要非线性激活函数5、Sigmoid函数6、Tanh函数7、ReLU函数8、多类分…

MFC 窗体插入图片

1.制作BMP图像1.bmp 放到res文件夹下&#xff0c;资源视图界面导入res文件夹下的1.bmp 2.添加控件 控件类型修改为Bitmap 图像&#xff0c;选择IDB_BITMAP1 3.效果

【嵌入式开发学习】__软件工程师的关键原则-18个系统设计概念

目录 前言 01. 域名系统 (DNS) 02. 负载均衡器 03. API 网关 04. 内容交付网络 (CDN) 05. 正向代理与反向代理 06. 缓存 07. 数据分区 08. 数据库复制 09. 分布式消息系统 10. 微服务 11. 数据库 12. 前端缓存 13. 后端缓存 14. 安全性 15. 高可用性与容错性 …

都是80m²小户型,凭啥她家那么好看!福州中宅装饰,福州装修

杨桥新苑 本案来自杨桥新苑的住宅&#xff0c; 质朴弥漫在80㎡的小家&#xff0c; 自然淡雅的木纹&#xff0c;精炼的玄关隔断&#xff0c; 简约的设计里传达着中式的静谧风雅&#xff0c; 简练的空间加入中国元素&#xff0c; 让人从进门开始就沾染一丝艺术气息。 风格&a…

Apache Pulsar 在腾讯云上的最佳实践

导语 由 StreamNative 主办的 Pulsar Meetup Beijing 2023 在2023年10月14日完美落幕&#xff0c;本次活动大咖云集&#xff0c;来自腾讯、滴滴、华为、智联招聘、RisingWave 和 StreamNative 的行业专家们一起&#xff0c;深入探讨 Pulsar 在生产环境中的最佳应用实践&#x…

Docker学习——②

文章目录 1、Docker是什么1.1 Docker本质1.2 Docker的引擎迭代1.3 Docker和虚拟机的区别1.4 Docker 为什么比虚拟机资源利用率高&#xff0c;启动快&#xff1f;1.5 Docker 和 JVM 虚拟化的区别&#xff1f; 2、Docker架构3、Docker生态3.1 新时代软件诉求3.2 Docker 解决方案 …

OSPF高级特性1(重发布,虚链路)

目录 OSPF高级特性(1) 一、OSPF不规则区域类型 二、解决方案 1、使用虚连接 演示一&#xff1a;非骨干区域无法和骨干区域保持连通 演示二&#xff1a;骨干区域被分割 2、使用多进程双向重发布 OSPF高级特性(1) 一、OSPF不规则区域类型 产生原因&#xff1a;区…

Linux ---------------------Shell 基本运算符

&#xff08;一&#xff09;摘要 Shell 和其他编程语言一样&#xff0c;支持多种运算符&#xff0c;包括&#xff1a; 算数运算符关系运算符布尔运算符字符串运算符文件测试运算符 原生bash不支持简单的数学运算&#xff0c;但是可以通过其他命令来实现&#xff0c;例如 awk …

喜讯!苏州箱讯获评苏州市软件和信息服务业 “头雁”培育企业

近日&#xff0c;由中国电子信息产业发展研究院、中国工业经济联合会、国家智能制造专家委员会、国家产业基础专家委员会、江苏省工业和信息化厅、江苏省国有资产监督管理委员会、苏州市人民政府共同主办的2023第三届中控中国大会在苏州太湖国际会议中心举办。 本届大会以“生态…

零基础成人英语哪里可以学,柯桥成人英语培训

写作中经常会用到“有利于”的表达&#xff0c;一说到“有利于”&#xff0c;大家最先想到的是 be good for 或者 benefit&#xff0c;很滥&#xff0c;很简单&#xff0c;没有亮点&#xff0c;写作中很难提分。 还有一点&#xff0c;英文写作中很忌讳相同的表达反复出现&…

Vue3入门指南:零基础小白也能轻松理解的学习笔记

文章目录 创建项目开发环境项目目录模板语法属性绑定条件渲染列表渲染事件处理内联事件处理器方法事件处理器&#xff08;常用&#xff09; 事件参数获取 event 事件事件传参 事件修饰符阻止默认事件阻止事件冒泡 数组变化侦测变更方法替换一个数组 计算属性class 绑定单对象绑…

【Python】多进程线程与CPU核数

多进程数量设置为CPU核数&#xff0c;或者略小于CPU核数&#xff1b;多线程数量&#xff0c;如果是CPU密集任务设为1&#xff1b;如果是IO密集设为合理的值&#xff1b;IO密集型&#xff1a;系统运作&#xff0c;大部分的状况是CPU 在等I/O &#xff08;硬盘/内存&#xff09;的…

Kafka基本原理、生产问题总结及性能优化实践 | 京东云技术团队

Kafka是最初由Linkedin公司开发&#xff0c;是一个分布式、支持分区的&#xff08;partition&#xff09;、多副本的&#xff08;replica&#xff09;&#xff0c;基于zookeeper协调的分布式消息系统&#xff0c;它的最大的特性就是可以实时的处理大量数据以满足各种需求场景&a…

逻辑(css3)_强制不换行

需求 如上图做一个跑马灯数据&#xff0c;时间、地点、姓名、提示文本字数都不是固定的。 逻辑思想 个人想法是给四个文本均设置宽度&#xff0c;不然会出现不能左对齐的现象。 此时四个文本均左对齐&#xff0c; 垂直排列样式也比较好看&#xff0c;但是出现一个缺点&#…

STM32-HAL库08-TIM的输出比较模式(输出PWM的另一种方式)

STM32-HAL库08-TIM的输出比较模式&#xff08;输出PWM的另一种方式&#xff09; 一、所用材料&#xff1a; STM32F103C6T6最小系统板 STM32CUBEMX&#xff08;HAL库软件&#xff09; MDK5 示波器或者逻辑分析仪 二、所学内容&#xff1a; 通过定时器TIM的输出比较模式得到预…

基于深度学习的视频多目标跟踪实现 计算机竞赛

文章目录 1 前言2 先上成果3 多目标跟踪的两种方法3.1 方法13.2 方法2 4 Tracking By Detecting的跟踪过程4.1 存在的问题4.2 基于轨迹预测的跟踪方式 5 训练代码6 最后 1 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 基于深度学习的视频多目标跟踪实现 …