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 集合

  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倍,线程安全;

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

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

相关文章

【flink】Task 故障恢复详解以及各重启策略适用场景说明

文章目录 一. 重启策略种类&#xff08;Restart Strategies&#xff09;1. Fixed Delay Restart Strategy2. Failure Rate Restart Strategy3. Fallback Restart Strategy4. No Restart Strategy 二. 故障恢复策略&#xff08;Failover Strategies&#xff09;1. &#xff08;全…

spring解决后端显示时区的问题

spring解决后端显示时区的问题 出现的问题&#xff1a; 数据库中的数据&#xff1a; 解决方法 spring:jackson:date-format: yyyy-MM-dd HH:mm:sstime-zone: Asia/Shanghai

【JAVA学习笔记】55 - 集合-Map接口、HashMap类、HashTable类、Properties类、TreeMap类(难点)

项目代码 https://github.com/yinhai1114/Java_Learning_Code/tree/main/IDEA_Chapter14/src/com/yinhai/map_ Map接口 一、Map接口的特点&#xff08;难点&#xff09; 难点在于对Node和Entry和EntrySet的关系 注意:这里讲的是JDK8的Map接口特点 Map java 1) Map与Collect…

学习python必会知识点:if条件判断语句的运用

大家早好、午好、晚好吖 ❤ ~欢迎光临本文章 如果有什么疑惑/资料需要的可以点击文章末尾名片领取源码 if的基本格式 if语句用来做判断&#xff0c;并选择要执行的语句分支。 基本格式如下&#xff1a; if CONDITION1:code_block(1) elif CONDITION2:code_block(2) elif CO…

删除文件要谨慎!如何在Linux中删除目录或文件

删除目录和文件是任何操作系统中最基本但最重要的功能之一。在Linux中,如果运行的是窗口环境,则可以使用文件管理器应用程序查找和删除文件。也许你是通过SSH远程登录的,或者你的Linux计算机没有安装GUI,或者你想对你要删除的内容有更多的控制权。与Linux中的任何东西一样,…

生产环境使用boost::fiber

简介 boost::fiber是一类用户级线程&#xff0c;也就是纤程。其提供的例子与实际生产环境相距较远&#xff0c;本文将对其进行一定的改造&#xff0c;将其能够投入到生产环境。 同时由于纤程是具有传染性的&#xff0c;使用纤程的代码里也全部要用纤程封装&#xff0c;本文将对…

appium如何连接多台设备

我们在做app自动化的时候&#xff0c;若要考虑兼容性问题&#xff0c;需要跑几台设备&#xff0c;要是一台一台的跑比较耗时&#xff0c;因此需要考虑使用多线程来同时操作多台设备。 1.我们拿两台设备来模拟操作下&#xff0c;使用&#xff1a;adb devices查看连接状况&#…

sass制作一个简单的星空背景

最近遇到一个有意思的东西&#xff0c;需要制作一个如下图的背景&#xff1a; 如果使用js或者canvas应该是比较简单的&#xff0c;正好最近在使用sass&#xff0c;那么纯sass能否实现这种效果呢&#xff1f;来试一下 首先来生成这些点&#xff1a; <div class"conten…

“恒山光量子”首秀!玻色量子联合移动云发表物理1区Top期刊SCPMA论文

2023年5月&#xff0c;北京玻色量子科技有限公司&#xff08;以下简称“玻色量子”&#xff09;联合移动云在我国知名科技期刊平台《中国科学&#xff1a;物理学 力学 天文学》英文版上发表了以“Optical experimental solution for the multiway number partitioning problem …

K8s集群

统一时间&#xff1a;ntpdate(都做) ntpdate -b ntp1.aliyun.com */1 * * * * /usr/sbin/ntpdate -b ntp1.aliyun.com systemctl status docker vi /etc/docker/daemon.json systemctl restart docker m: vim kubernetes.sh cat >> /etc/yum.repos.d/kubernetes.repo…

中国电子学会主办 第四届ATEC科技精英赛报名启动

11月1日由中国电子学会主办的第四届ATEC科技精英赛&#xff08;ATEC2023&#xff09;正式启动报名。 ATEC科技精英赛是主要面向中国籍计算机等专业在校学生、人工智能及网络安全行业研究者和从业者的一场高水平的智能科技挑战赛&#xff0c;意在贯彻落实党中央、国务院关于推动…

【OpenCV实现图像梯度,Canny边缘检测】

文章目录 概要图像梯度Canny边缘检测小结 概要 OpenCV中&#xff0c;可以使用各种函数实现图像梯度和Canny边缘检测&#xff0c;这些操作对于图像处理和分析非常重要。 图像梯度通常用于寻找图像中的边缘和轮廓。在OpenCV中&#xff0c;可以使用cv2.Sobel()函数计算图像的梯度…

期 货 跟 单/资 管 分 仓/镜像跟单/外 盘 分 仓的全面介绍!

期货跟单是经过科学的筛选找出合格的目标样本数据然后利用样本交易数据转化成未来实际账面利润的综合性过程。 期货跟单分为正向跟单和反向跟单&#xff0c;简单地说就是找出期高手正向跟随高手赚取收益或找出期货低手反向跟随赚取收益。 期货跟单软件是实现跟单过程自动化的工…

设计思想培养:装饰者模式下的RecyclerView添加头、尾

用一个设计模式培养高复用、低耦合思想 前言Android中的装饰者代码实现第一步&#xff1a;创建装饰器DecorateAdapter第二步&#xff1a;处理头部、中间内容、尾部的绑定关系第三步&#xff1a;装饰器的使用第四步&#xff1a;改进、直接封装一个View出来 总结 前言 一个高复用…

SpringCloud Gateway实现请求解密和响应加密

文章目录 前言正文一、项目简介二、核心代码2.1 自定义过滤器2.2 网关配置2.3 自定义配置类2.4 加密组件接口2.5 加密组件实现&#xff0c;AES算法2.6 启动类&#xff0c;校验支持的算法配置 三、请求报文示例四、测试结果4.1 网关项目启动时4.2 发生请求时 前言 本文环境使用比…

UI动效的都可以用哪些工作来制作

随着UI设计的不断发展&#xff0c;UI动效越来越多地应用于现实生活中。手机&#xff0c;iPad、计算机、网页和其他设备被广泛使用&#xff0c;所以问题来了&#xff0c;为什么UI动态效果越来越被广泛使用&#xff1f;它的优点是什么&#xff1f;哪些软件可以设计UI动态效果&…

车载测试相比软件测试,前景会稍好一点吗?

> 如果个人是汽车、电气、工业工程相关专业的学历背景&#xff0c;那可以考虑从事车载测试&#xff08;看上图&#xff09;。> 如果不是以上专业&#xff0c;那就要慎重啦。 车载测试是测试行业的一个分支&#xff0c;最近十年一直存在&#xff0c;并不是这一两年才有的…

python 数据挖掘库orange3 介绍

orange3 是一个非常适合初学者的data mining library. 它让使用者通过拖拽内置的组件来形成工作流。让你不需要写任何代码就可以体验到数据挖掘和可视化的魅力。 它的桌面如下&#xff0c;这里我创建了 3 个节点&#xff0c;分别是数据集、小提琴图&#xff0c;散点图 其中 …

UE5——网络——RPC

RPC&#xff08;这个是官方文档的资料&#xff09; 要将一个函数声明为 RPC&#xff0c;您只需将 Server、Client 或 NetMulticast 关键字添加到 UFUNCTION 声明。 例如&#xff0c;若要将某个函数声明为一个要在服务器上调用、但需要在客户端上执行的 RPC&#xff0c;您可以…