Java集合相关面试题(2024大厂高频面试题系列)

1、说一说Java提供的常见集合?(画一下集合结构图)
在这里插入图片描述

在java中提供了量大类的集合框架,主要分为两类:

第一个是Collection 属于单列集合,第二个是Map 属于双列集合

在Collection中有两个子接口List和Set。在平常开发的过程中用的比较多的list接口中的实现类ArrarList和LinkedList。 在Set接口中有实现类HashSet和TreeSet。

在map接口中有很多的实现类,平时比较常见的是HashMap、TreeMap,还有一个线程安全的map:ConcurrentHashMap。

2、ArrayList底层是如何实现的?

我阅读过arraylist的源码,我主要说一下add方法吧
在这里插入图片描述

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

3、ArrayList list=new ArrayList(10)中的list扩容几次

在ArrayList的源码中提供了一个带参数的构造方法,这个参数就是指定的集合初始长度,所以给了一个10的参数,就是指定了集合的初始长度是10,这里面并没有扩容。

4、如何实现数组和List之间的转换?

数组转list,可以使用jdk自动的一个工具类Arrars,里面有一个asList方法
可以转换为数组。

List 转数组,可以直接调用list中的toArray方法,需要给一个参数,指定数组的类型,需要指定数组的长度。

5、用Arrays.asList转List后,如果修改了数组内容,list受影响吗?List用toArray转数组后,如果修改了List内容,数组受影响吗?

Arrays.asList转换list之后,如果修改了数组的内容,list会受影响,因为它的底层使用的Arrays类中的一个内部类ArrayList来构造的集合,在这个集合的构造器中,把我们传入的这个集合进行了包装而已,最终指向的都是同一个内存地址。

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

6、ArrayList 和 LinkedList 的区别是什么?
它们两个主要是底层使用的数据结构不一样,ArrayList 是动态数组,LinkedList 是双向链表。数组易于查询操作,链表易于增删操作。

7、ArrayList和LinkedList都不是线程安全的,是如何解决这个的线程安全问题的?

主要有两种解决方案:
第一:我们使用这个集合,优先在方法内使用,定义为局部变量,这样的话,就不会出现线程安全问题。

第二:如果非要在成员变量中使用的话,可以使用线程安全的集合来替代
ArrayList可以通过Collections 的 synchronizedList 方法将 ArrayList 转换成线程安全的容器后再使用。
LinkedList 换成ConcurrentLinkedQueue来使用。

8、说一下HashMap的实现原理?
它主要分为了一下几个部分:
1,底层使用hash表数据结构,即数组+(链表 | 红黑树)
2,添加数据时,计算key的值确定元素在数组中的下标key相同则替换不同则存入链表或红黑树中
3,获取数据通过key的hash计算数组下标获取元素

9、HashMap的jdk1.7和jdk1.8有什么区别?

JDK1.8之前采用的拉链法,数组+链表
JDK1.8之后采用数组+链表+红黑树,链表长度大于8且数组长度大于64则会链表转化为红黑树,红黑树拆分成的树结点小于等于6个会转化为链表。

10、你能说下HashMap的put方法的具体流程吗?

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

11、能讲一讲HashMap的扩容机制吗?

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

12、你了解hashMap的寻址算法吗?

这个哈希方法首先计算出key的hashCode值,然后通过这个hash值右移16位后的二进制进行按位异或运算得到最后的hash值。

在putValue的方法中,计算数组下标的时候使用hash值与数组长度取模得到存储数据下标的位置,hashmap为了性能更好,并没有直接采用取模的方式,而是使用了数组长度-1 得到一个值,用这个值按位与运算hash值,最终得到数组的位置。

13、为什么HashMap的数组长度一定是2的次幂?
hashmap这么设计主要有两个原因:
第一:
计算索引时效率更高:如果是 2 的 n 次幂可以使用位与运算代替取模
第二:
扩容时重新计算索引效率更高:在进行扩容是会进行判断 hash值按位与运算旧数组长度是否 == 0
如果等于0,则把元素留在原来位置 ,否则新位置是等于旧位置的下标+旧数组长度

14、你知道hashmap在1.7情况下的问题吗?
存在死循环问题
jdk7的的数据结构是:数组+链表

在数组进行扩容的时候,因为链表是头插法,在进行数据迁移的过程中,有可能导致死循环

当然,JDK 8 将扩容算法做了调整,不再将元素加入链表头(而是保持与扩容前一样的顺序),尾插法,就避免了jdk7中死循环的问题

15、hashmap是线程安全的吗,如果不安全怎么做,讲下其原理?

不是线程安全的

我们可以采用ConcurrentHashMap进行使用,它是一个线程安全的
HashMap,jdk1.7和1.8也做了很多调整。

JDK1.7的底层采用是分段的数组+链表 实现
JDK1.8 采用的数据结构跟HashMap1.8的结构一样,数组+链表/红黑二叉树

在jdk1.7中 ConcurrentHashMap 里包含一个 Segment 数组。Segment 的结构和HashMap类似,是一 种数组和链表结构,一个 Segment 包含一个HashEntry 数组,每个 HashEntry 是一个链表结构 的元素,每个 Segment 守护着一个HashEntry数组里的元素,当对 HashEntry 数组的数据进行修 改时,必须首先获得对应的 Segment的锁。

Segment 是一种可重入的锁 ReentrantLock,每个 Segment 守护一个
HashEntry 数组里得元 素,当对 HashEntry 数组的数据进行修改时,必须首先获得对应的 Segment 锁

在jdk1.8中的ConcurrentHashMap 做了较大的优化,性能提升了不少。首先是它的数据结构与jdk1.8的hashMap数据结构完全一致。其次是放弃了Segment的设计,取而代之的是采用Node + CAS + Synchronized来保 证并发安全进行实现,synchronized只锁定当前链表或红黑二叉树的首节点,这样只要hash不冲 突,就不会产生并发 , 效率得到提升

16、HashSet与HashMap的区别?
HashSet底层其实是用HashMap实现存储的, HashSet封装了一系列HashMap的方法. 依靠HashMap来存储元素值,(利用hashMap的key键进行存储), 而value值默认为Object对象. 所以HashSet也不允许出现重复值, 判断标准和HashMap判断标准相同, 两个元素的hashCode相等并且通过equals()方法返回true。

17、HashTable与HashMap的区别?
第一,数据结构不一样,hashtable是数组+链表,hashmap在1.8之后改为了数组+链表+红黑树
第二,hashtable存储数据的时候都不能为null,而hashmap是可以的
第三,hash算法不同,hashtable是用本地修饰的hashcode值,而hashmap经常了二次hash
第四,扩容方式不同,hashtable是当前容量翻倍+1,hashmap是当前容量翻倍
第五,hashtable是线程安全的,操作数据的时候加了锁synchronized,
hashmap不是线程安全的,效率更高一些

在实际开中不建议使用HashTable,在多线程环境下可以使用
ConcurrentHashMap类

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

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

相关文章

【力扣hot100】刷题笔记Day14

前言 又是新的一周,快乐的周一,快乐地刷题,今天把链表搞完再干活! 114. 二叉树展开为链表 - 力扣(LeetCode) 前序遍历 class Solution:def flatten(self, root: Optional[TreeNode]) -> None:if not r…

回溯 Leetcode 51 N皇后

N皇后 Leetcode 51 学习记录自代码随想录 按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。 n 皇后问题 研究的是如何将 n 个皇后放置在 nn 的棋盘上,并且使皇后彼此之间不能相互攻击。 给你一个整数 n ,返回所…

Linux —— 链接文件

硬链接 一般情况下,文件名和inode号码是"一一对应"关系,每个inode号码对应一个文件名。但是,Unix/Linux系统允许,多个文件名指向同一个inode号码。 这意味着,可以用不同的文件名访问同样的内容;对…

软件开发常见模型解析

软件开发常见模型解析 摘要:本文将为您详细介绍软件开发过程中常见的几种模型,包括瀑布模型、敏捷开发模型、螺旋模型、迭代模型和原型模型。通过了解这些模型的原理、优缺点,帮助您在不同的软件项目中选择最适合的开发模型。 一、引言 在…

【IC前端虚拟项目】inst_buffer子模块DS与RTL编码

【IC前端虚拟项目】数据搬运指令处理模块前端实现虚拟项目说明-CSDN博客 需要说明一下的是,在我所提供的文档体系里,并没有模块的DS文档哈,因为实际项目里我也不怎么写DS毕竟不是每个公司都和HISI一样对文档要求这么严格的。不过作为一个培训的虚拟项目,还是建议在时间充裕…

Docker技术概论(3):Docker 中的基本概念

Docker技术概论(3) Docker 中的基本概念 - 文章信息 - Author: 李俊才 (jcLee95) Visit me at: https://jclee95.blog.csdn.netMy WebSite:http://thispage.tech/Email: 291148484163.com. Shenzhen ChinaAddress of this article:https://…

基于java+springboot女士电商平台系统源码+文档设计

基于javaspringboot女士电商平台系统源码文档设计 博主介绍:多年java开发经验,专注Java开发、定制、远程、文档编写指导等,csdn特邀作者、专注于Java技术领域 作者主页 央顺技术团队 Java毕设项目精品实战案例《1000套》 欢迎点赞 收藏 ⭐留言 文末获取源…

C语言----动态内存管理(2)

1.这里总结动态内存管理里面的错误 (1)使用malloc开辟空间以后直接赋值 这个就是malloc开辟失败返回空指针,直接给空指针赋值就是错误的, tip1:使用malloc开辟空间以后一定要判断是否为空 (2) 越界访问…

Python批量提取文件夹中图片的名称及路径到指定的.txt文件中

目录 一、代码二、提取效果 一、代码 import os# 定义要保存的文件名 file_name "TestImage/Image_Visible_Gray.txt"# 读取文件夹路径 folder_path "TestImage/Image_Visible_Gray"# 遍历文件夹中的所有文件 with open(file_name, "w") as f…

IO进程线程day1

编写链表&#xff0c;链表里面随便搞点数据&#xff0c;使用fprintf将链表中所有的数据保存到文件中&#xff0c;用fscanf读取文件中的数据写入链表中 #include <stdio.h> #include <stdlib.h>typedef struct Node {int data;struct Node* next; } Node;// 创建新…

可移植性(兼容性)测试指南

可移植性是指应用程序能够安装到不同的环境中&#xff0c;在不同的环境中使用&#xff0c;甚至可以移动到不同的环境中。当然&#xff0c;前两者对所有系统都很重要。就PC软件而言&#xff0c;鉴于操作系统、共存和互操作应用程序、硬件、带宽可用性等方面的快速变化&#xff0…

抖店如何运营?新手应该怎么做?从入门到精通详细讲解!

我是电商珠珠 做抖店必须先搞懂它的基础流程&#xff0c;流程搞懂了&#xff0c;才能有进一步的可能。不要急功近利&#xff0c;想要一口吃个胖子&#xff0c;这样做就会直接造成店铺被清店&#xff0c;扣除保证金&#xff0c;甚至还会埋怨自己没用。 我做电商已经三年多的时…

vue3 日期延后一天

问题&#xff1a;提交信息时要求将所选日期延后一天进行提交解决过程&#xff1a;1.定义延后一天的计算方法&#xff0c;在提交前&#xff0c;将提交日期传入调用该方法 2.对延后的日期进行格式化&#xff0c;最后格式为yy-mm-dd解决结果&#xff1a; const…

c++ - pointer convert - class member function‘s pointer <==> void*

文章目录 c - pointer convert - class member functions pointer <> void*概述笔记END c - pointer convert - class member function’s pointer <> void* 概述 想将结构体中的void指针赋值为类成员函数的指针, 用于回调. 这个结构体相关的函数写完, 就不用再因…

Stable Diffusion中的Clip模型

基础介绍 Stable Diffusion 是一个文本到图像的生成模型&#xff0c;它能够根据用户输入的文本提示&#xff08;prompt&#xff09;生成相应的图像。在这个模型中&#xff0c;CLIP&#xff08;Contrastive Language-Image Pre-training&#xff09;模型扮演了一个关键的角色&a…

Biotin aniline,生物素苯胺,用于研究蛋白质结构和功能

您好&#xff0c;欢迎来到新研之家 文章关键词&#xff1a;769933-15-5&#xff0c;Biotin aniline&#xff0c;生物素苯胺&#xff0c;Biotin-aniline&#xff0c;生物素-苯胺 一、基本信息 【产品简介】&#xff1a;Biotin aniline is composed of three parts: biotin, w…

个人或者小团队选择C语言还是c++?

个人或者小团队选择C语言还是c? 在开始前我有一些资料&#xff0c;是我根据网友给的问题精心整理了一份「C语言的资料从专业入门到高级教程」&#xff0c; 点个关注在评论区回复“888”之后私信回复“888”&#xff0c;全部无偿共享给大家&#xff01;&#xff01;&#xff0…

使用Python语言实现一个基于动态数组的序列队列

一、动态数组的实现 首先&#xff0c;我们需要创建一个DynamicArray类&#xff0c;该类将管理我们的动态数组。 动态数组能够动态地调整其大小&#xff0c;以容纳更多的元素。 目录 一、动态数组的实现 代码示例&#xff1a; 二、序列队列的实现 接下来&#xff0c;我…

学习JAVA的第八天(基础)

目录 多态 前提 形式 测试类 调用成员的特点 优势 劣势 包 注意事项&#xff1a; final关键字 常量 命名规范&#xff1a; 注意事项&#xff1a; 权限修饰符 分类 代码块 局部代码块 构造代码块 静态代码块 抽象类 抽象类&#xff1a; 定义格式 抽象…

代码随想录算法训练营第五天

● 自己看到题目的第一想法 242. 有效的字母异位词 方法&#xff1a; 方法一&#xff1a; 暴力法 1. 分别对s, t排序 2. 遍历s与t 判断s[i]!t[i] 返回 false 否则 返回true思路&#xff1a; 注意&#xff1a; 代码&#xff1a; bool cmp(char a, char b){return a<b;…