Java集合面试题

Java集合框架

    • 1、List、Set、Map的区别
    • 2、ArrayList、LinkedList、Vector区别
    • 3、为什么数组索引从0开始,而不是从1开始?
    • 4、ArrayList底层的实现原理
    • 5、红黑树、散列表
    • 6、HashMap的底层原理
    • 7、HashMap的put方法具体流程
    • 8、HashMap的扩容机制
    • 9、HashMap是怎么解决哈希冲突?
    • 10、HashMap寻址算法
    • 11、HashMap在1.7下的多线程死循环问题
    • 12、HashMap、Hashtable、LinkedHashMap、TreeMap、ConcurrentSkipListMap选择
    • 13、CocurrentHashMap底层原理
    • 14、CopyOnWriteArrayList
    • 15、

1、List、Set、Map的区别

在这里插入图片描述

2、ArrayList、LinkedList、Vector区别

  • ArrayList基于动态数组实现,LinkedList基于双向链表实现
  • ArrayList比LinkedList在随机访问时效率要更高,因为LinkedList是链表存储,要移动指针从前往后寻找。
  • 在非首尾的增删操作时,LinkedList要比ArrayList效率高,因为ArrayList增删数据要先将插入或删除的后续元素后依次向后或向前移动。
  • ArrayList和Vector的迭代器实现都是fail-fast的,两者允许null值,也可以使用索引值对元素进行随机访问。两者都是基于索引的,内部由一个数组支持,即都维护插入的顺序,可以根据插入顺序来获取元素。
  • ArrayList是非线程安全的,Vector是线程安全的,ArrayList比Vector快,但一般需要保证线程安全可使用CopyOnWriteArrayList.来代替Vector。
    在这里插入图片描述

3、为什么数组索引从0开始,而不是从1开始?

  • 在根据数组索引获取元素的时候,会用索引和寻址公式来计算内存所对应的元素数据,寻址公式:数组的首地址 + 索引*存储数据的类型大小。
  • 如果数组的索引从1开始,寻址公式中,就需要增加一次减法操作,对于CPU来说就多了一次指令,性能不高。

4、ArrayList底层的实现原理

  • ArrayList底层是用动态数组实现的
  • ArrayList初始容量为0,当第一次添加数据的时候才会初始化容量为10
  • ArrayList在进行扩容的时候是按原来的1.5倍,每次扩容都需要拷贝数组
  • ArrayList在添加数据时
    1)确保数组已使用长度加1之后足够存下下一个数据
    2)计算数组的容量,如果当前数组已使用长度+ 1后大于当前的数组长度,则会调用扩容方法,扩大为原来的1.5倍
    3)确保新增的数据有地方存储之后,则将新元素添加到位于size的位置上。
    4)返回是否添加成功

ArrayList list = new ArrayList(10)中list扩容几次:

  • 该语句只是声明和实例了一个ArrayList对象,指定了初始容量为10,未扩容

数组与ArrayList之间的转换:

  • 可以使用Arrays.asList()来将数组转换成List,使用List中的toArray方法转成数组
  • 使用Arrays.asList()来将数组转换成List后,如果改变原数组的数据,list的数组也会随之改变,因为asList的底层使用的是Arrays类中的一个内部类ArrayList来构造的集合,在这个集合的构造器中,把我们传入的这个集合进行了包装,最终指向的都是同一个内存地址。
  • list用toArray转数组后,如果修改了list内容,数组不会影响,当调用了toArray以后,在底层是进行了数组的拷贝,跟原来的数组没关系了。
    在这里插入图片描述

5、红黑树、散列表

  • 红黑树
    红黑树是一种自平衡的二叉搜索树(BST);
    所有的红黑规则都是希望红黑树能够保证平衡;
    红黑树的时间复杂度:查找、添加、删除都是O(logn)

  • 红黑树的性质
    1)节点要么是红色、要么是黑色
    2)根节点是黑色
    3)叶子节点都是黑色的空节点
    4)红黑树中红色节点的子节点都是黑色
    5)从任一节点到叶子节点的所有路径都包含相同数目的黑色节点

  • 散列表
    散列表又称哈希表,是根据键直接访问在内存存储位置值的数据结构,是由数组演化而来的,利用了数组支持按照下标进行随机访问的特性。
    在散列表中,数组的每个下标位置我们可以称之为桶或槽,每个桶会对应一条链表,所有散列值相同的元素我们都放到相同槽位对应的链表中。

6、HashMap的底层原理

  • HashMap底层使用hash表数据结构,即数组+链表+红黑树实现的。添加数据时,计算key的值确定元素在数组中的下标,key相同则替换,不同则存入链表或红黑树中。

在这里插入图片描述

7、HashMap的put方法具体流程

  • 判断键值对数据table是否为空或null,否则执行resize()进行扩容(初始化)
  • 根据键值key计算hash值得到数组索引
  • 判断table[i] 是否等于null,如果元素为空,则直接新建节点添加
  • 如果table[i]元素不为空,则分情况讨论:
    1)判断table[i]的首个元素是否和key一样,如果相同直接覆盖value
    2)判断table[i]是否是红黑树,如果是红黑树,则直接在树中插入键值对
    3)遍历table[i],链表的尾部插入数据,然后判断链表长度是否大于8,大于8的话把链表转换为红黑树,在红黑树中执行插入操作,遍历过程中若发现key已经存在直接覆盖value。
  • 插入成功后,判断实际存在的键值对数量size是否超过了最大容量threshold(数组长度*0.75),如果超过,进行扩容。

在这里插入图片描述
在这里插入图片描述

8、HashMap的扩容机制

  • 在添加元素或初始化的时候需要调用resize方法进行扩容,第一次添加数据初始化数组长度为16,以后每次扩容都是达到了扩容阈值(数组长度*0.75)
  • 每次扩容时,都是扩容之前容量的2倍;
  • 扩容之后,会新创建一个数组,需要把老数组中的数据挪动到新的数组中
    1)没有hash
  • 冲突的节点,则直接计算新数组的索引位置(e.hash & (newCap - 1))
  • 如果是红黑树,走红黑树的添加
  • 如果是链表,则需要遍历链表,可能需要拆分链表,判断(e.hash & newCap)是否为0,该元素要么停留在原始位置,要么移动到原址位置+增加的数组大小这个位置上。

在这里插入图片描述
在这里插入图片描述

9、HashMap是怎么解决哈希冲突?

在这里插入图片描述

10、HashMap寻址算法

  • 计算对象的hashCode值,再进行调用hash()方法进行二次哈希,hashcode值右移16位再异或运算,让哈希分布更均匀,最后(capacity - 1) & hash 得到索引。
  • HashMap的数组长度为什么一定是2的次幂?
    1)计算索引时效率更高:如果是2的n次幂可以使用位与运算代替取模
    2)扩容时重新计算索引效率更高:hash & oldCap == 0 的元素留在原来位置,否则新位置= 旧位置 + oldCap

11、HashMap在1.7下的多线程死循环问题

  • 在jdk1.7的HashMap中在数组进行扩容的时候,因为链表是头插法,在进行数据迁移的过程中,有可能导致死循环。
    如:有两个线程:
    线程一:读到当前的HashMap数据,数据中一个链表,在准备扩容时,线程二介入。
    线程二:也读取HashMap,直接进行扩容。因为是头插法,链表的顺序会进行颠倒过来,比如原来的顺序是AB,扩容后的顺序变成了BA,线程二执行结束。
    线程一:继续执行的时候就会出现死循环问题。
    线程一先将A移入新的链表,再将B插入到链头,由于另外一个线程的原因,B的next指向了A,所以B->A->B形成循环。当然,jdk8将扩容算法做了调整,不再将元素加入链表头(而是保持与扩容前一样的顺序),尾插法,就避免了jdk7中的死循环问题。

12、HashMap、Hashtable、LinkedHashMap、TreeMap、ConcurrentSkipListMap选择

  • HashMap:没有锁机制,非线程安全,但效率比HashTable要高,允许key和value为null。不保证有序性,即遍历的顺序与put顺序不一定一致
  • Hashtable:内部方法都是synchronized(同步锁)修饰的,即线程安全键值只要有一个是null,就出现空指针异常
  • HashMap提供对key的Set进行遍历,因此它是fail-fast的,但HashTable提供对key的Enumeration进行遍历,它不支持fail-fast。
  • LinkedHashMapLinkedHashMap保持有序性,遍历的顺序与put顺序一致。在]ava1.4中引入了LinkedHashMap,是HashMap的一个子类,假如你想要遍历顺序,你很容易从HashMap转向LinkedHashMap,但是Hashtable不是这样的,它的顺序是不可预知的。
  • TreeMap:实现了SortedMap接口,保证了有序性,默认排序是根据key值进行排序,也可重写comparator方法根据key进行排序。
  • ConcurrentSkipListMap:对于并发环境下的有序 Map 操作,ConcurrentSkipListMap 的性能优于 TreeMap。TreeMap 不是线程安全的,而 ConcurrentSkipListMap 提供了一种线程安全且高并发的有序 Map 实现。

总结:不要求保证有序性,使用HashMap,要求不改变put顺序使用LinkedHashMap,根据key排序使用TreeMap。需保证线程安全问题使用CocurrentHashMap。Hashtable是被认为一个遗留类,效率低,一般不使用。既要求线程安全,又要求有序可使用ConcurrentSkipListMap。

13、CocurrentHashMap底层原理

  • jdk1.7底层采用分段的数组+链表实现。采用Segment分段锁,底层使用的是ReentrantLock。
  • jdk1.8采用的数据结构跟HashMap1.8的结构一样,数组+链表+红黑树。采用CAS添加新节点,采用synchronized锁定链表或红黑二叉树的首节点,相对Segment分段锁粒度更细,性能更好。

在这里插入图片描述

14、CopyOnWriteArrayList

  • 首先CopyOnWriteArrayList内部也是用数组来实现的,线程安全的并发集合,向CopyOnWriteArrayList添加元素时,会复制一个新的数组,写操作在新数组上进行,读操作在原数组上进行。并且,写操作会加锁,防止出现并发写入丢失数据的问题,写操作结束后会把原数组指向新数组,CopyOnWriteArrayList允许在写操作时来读取数据,大大提高了读的性能,因此适合读多写少的应用场景,但是CopyOnWriteArrayList会比较占内存,同时可能读到的数据不是实时更新的数据,所以不适合实时性要求很高的场景

15、

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

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

相关文章

南方科技大学马永胜教授给年轻人使用AI工具上的建议

摘要 - 1. AI的未来,是机器人和机器人之间的合作; 2. 行业的发展方向是需求决定的,不要做同质化的发展,要做专/精/特/新; 3. 新质生产力 ( 科学技术革命性突破 生产要素创新型配置 产业深度转型升级&…

java通过poi-tl导出word实战详细步骤

文章目录 与其他模版引擎对比1.引入maven依赖包2.新建Word文档exportWprd.docx模版3.编写导出word接口代码4.导出成果 poi-tl是一个基于Apache POI的Word模板引擎,也是一个免费开源的Java类库,你可以非常方便的加入到你的项目中,并且拥有着让…

贪心算法-以高校教材管理系统为例

1.贪心算法介绍 1.算法思路 贪心算法的基本思路是从问题的某一个初始解出发一步一步地进行,根据某个优化测度,每一 步都要确保能获得局部最优解。每一步只考虑一 个数据,其选取应该满足局部优化的条件。若下 一个数据和部分最优解连在一起…

Pix4Dmapper:无人机测绘的革命性工具

在现代测绘和地理信息系统(GIS)领域,Pix4Dmapper无疑是一款革命性的工具。作为一名长期使用这款软件的用户,我深深感受到它在工作中的重要性和便利性。Pix4Dmapper不仅仅是一款软件,更是测绘工作者的得力助手&#xff…

285个地级市出口产品质量及技术复杂度(2011-2021年)

出口产品质量与技术复杂度:衡量国家竞争力的关键指标 出口产品质量是衡量国内企业生产的产品在国际市场上竞争力的重要标准。它不仅要求产品符合国际标准和目标市场的法律法规,而且需要保证产品质量的稳定性和可靠性。而出口技术复杂度则进一步体现了一…

新一代信息技术及应用

关于云计算的描述不正确的是( )。 A 云计算可以通过网络连接,用户通过网络接入“云”中并获得有关的服务,“云”内节点之间也通过内部的网络相连 B 云计算可以快速、按需、弹性服务,用户可以按照实际需求迅速获取或释放…

[Python学习篇] Python面向对象——类

面向对象是什么? 面向对象(Object-Oriented Programming,简称OOP)是一种编程范式,它使用“对象”来设计应用程序和计算机程序。OOP的核心概念包括类(Class)、对象(Object&#xff09…

批量下载手机中APP程序中文件

需求 利用 adb pull 下载手机中app的某目录 adb pull 命令本身不支持直接下载整个目录(文件夹)及其所有子目录和文件作为一个单一的操作。但是,可以通过一些方法来间接实现这一目的。 方法 1. 首先将要下载的目录进行 tar 打包 # 在 And…

Python面试题:Python 中的 `property` 函数有什么用?

在 Python 中,property 函数用于创建和管理类中的属性。它允许你将方法转换为属性,这样你可以像访问变量一样访问这些方法。这对于控制属性的访问和修改非常有用,因为它允许你在属性访问时执行额外的逻辑(如验证或计算&#xff09…

光通信领域常见的会议和期刊总结

在高速光通信小组待了一年,对我们领域主要的会议和期刊也有了一定的了解,所以总结一下我们可以投的期刊或会议有哪些。会议一般有OFC、ECOC、CLEO、OECC、ACP等,期刊则有OE、OL、PTL、JLT、PJ、AO、JOSA等,下面简单介绍一下。 先…

【atcoder】习题——位元枚举

题意:求i&M的popcount的和,i属于0……N 主要思路还是变加为乘。 举个例子N22,即10110 假设M的第3位是1,分析N中: 00110 00111 00100 00101 发现其实等价于 0010 0011 0000 0001 也就是左边第4位和第5…

算法学习笔记(8.1)-动态规划入门

目录 问题特性: 最优子结构: 代码示例:(动态规划最优子结构) 上述最小代价爬楼梯的运行过程: 代码示例: 无后效性: 解析: 具体过程图示如下: 具体的…

如何为IP申请SSL证书

目录 以下是如何轻松为IP地址申请SSL证书的详细步骤: 申请IP证书的基本条件: 申请IP SSL证书的方式: 确保网络通信安全的核心要素之一,是有效利用SSL证书来加密数据传输,特别是对于那些直接通过IP地址访问的资源。I…

使用 Azure DevOps Pipelines 生成 .NET Core WebJob 控制台应用 CI/CD

Web 应用程序通常需要作为后台任务运行的进程,并在特定时间间隔进行计划或在事件中触发。它们不需要花哨的 IO 接口,因为重点是过程而不是输出。Azure WebJobs 提供了出色的支持,通常在云环境中通过 Web 控制台应用程序来实现此目的。WebJob …

企业数字化转型中的低代码开发平台应用:释放创新潜能

随着信息技术的飞速发展,企业数字化转型已成为行业趋势。在这场转型浪潮中,低代码开发平台以其独特的优势,成为众多企业实现快速迭代、高效创新的得力助手。本文将深入探讨低代码开发平台在企业数字化转型中的应用,以及如何帮助企…

Mac平台虚拟机 Parallels Desktop v19.4.1,支持M1/M2/M3芯片组

Parallels Desktop for Mac是功能强大灵活度高的虚拟化方案,无需重启即可在同一台电脑上随时访问Windows和Mac两个系统上的众多应用程序。从仅限于PC的游戏到生产力软件,Parallels Desktop都能帮您实现便捷使用。Parallels Desktop 是一款专业的Mac虚拟机…

Docker搭建kafka+zookeeper以及Springboot集成kafka快速入门

参考文章 【Docker安装部署KafkaZookeeper详细教程】_linux arm docker安装kafka-CSDN博客 Docker搭建kafkazookeeper 打开我们的docker的镜像源配置 vim /etc/docker/daemon.json 配置 { "registry-mirrors": ["https://widlhm9p.mirror.aliyuncs.com"…

vue父子组件通信实现模糊搜索功能

我遇到的问题: 我的搜索框在父页面,静态数据都在子页面。怎么实现模糊查询数据? 昨天的尝试:先把搜索的内容数据存到session里,然后从session里拿, 结果:存是存进去了,却拿不到。应…

Django学习收尾

启动项目命令 python manage.py runserver 文件上传功能实现 title "Form上传"if request.method "GET":form UpForm()return render(request, upload_form.html, {"form": form, "title": title})form UpForm(datarequest.POS…

Java对象创建究竟是在栈上还是堆上??

在 Java 中,对象的创建通常情况下是在堆上。 基本数据类型(如 byte、short、int、long、float、double、char)在方法内声明时,其值会存储在栈上。除了基本数据类型之外的所有对象,都是由 Java 虚拟机(JVM&…