[2024最新] java八股文实用版(附带原理)---java集合篇

介绍一下常见的list实现类?

ArrayList
线程不安全,内部是通过数组实现的,继承了AbstractList,实现了List,适合随机查找和遍历,不适合插入和删除。排列有序,可重复,当容量不够的时候,会将原容量增加50%(即乘以1.5)。
​
LinkedList
LinkedList 是用链表结构存储数据的,线程不安全。很适合数据的动态插入和删除,随机访问和遍历速度比较慢,增删快。另外,他还提供了 List 接口中没有定义的方法,专门用于操作表头和表尾元素,可以当作堆栈、队列和双向队列使用。底层使用双向链表数据结构。
​
Vector(数组实现、线程同步)
Vector 与 ArrayList 一样,也是通过数组实现的,Vector和ArrayList用法上几乎相同,但Vector比较古老,一般不用。Vector是线程同步的,效率低。即某一时刻只有一个线程能够写 Vector,避免多线程同时写而引起的不一致性,但实现同步需要很高的花费,因此,访问它比访问 ArrayList 慢。默认扩展一倍容量。

ArrayList初始容量是多少?

ArrayList 默认的初始容量是 10。意味着当你创建一个新的 ArrayList 而不指定其容量时,它会以一个内部数组长度为 10 的数组来开始。当添加的元素数量超过这个初始容量时,ArrayList 的内部数组会进行扩容,通常是增长为原来的 1.5 倍。

ArrayList是如何扩容的?

1.一个新的ArrayList对象时,它通常会分配一个初始容量为10。
2.当向ArrayList中添加一个新元素,并且该元素的数量超过当前数组的容量时,就会触发扩容操作
3.扩容公式:newCapacity = oldCapacity + (oldCapacity >> 1),这实际上是将原容量增加50%(即乘以1.5)。
4、扩容过程:创建一个新的数组,其长度为新计算的容量。将原数组中的所有元素复制到新数组中。将ArrayList的内部引用从原数组更新为新数组。将新元素添加到新数组的末尾。
ArrayList的添加与删除元素为什么慢?
ArrayList的添加与删除操作慢,主要是因为其内部实现基于数组,而数组在插入和删除元素时需要移动其他元素来保证连续性和顺序性,这个过程需要耗费较多的时间。

java容器有哪些?

ArrayList如何保证线程安全?

1.借助锁:可以通过在访问 ArrayList 的代码块上使用 synchronized 关键字来手动同步对 ArrayList 的访问。这要求所有访问 ArrayList 的代码都知道并使用相同的锁。
2.使用 Collections.synchronizedList

聊聊常见set类都有哪几种?

HashSet
HashSet线程不安全,基于哈希表实现,具有快速的插入、删除和查找操作。不保证元素的迭代顺序,允许null元素的存在,但只能有一个null元素。
​
LinkedHashSet
LinkedHashSet是HashSet的子类,基于哈希表和双向链表实现,可以维护元素的插入顺序。相比于 HashSet 增加了顺序性,因此当需要保持元素插入顺序时,可以选择使用LinkedHashSet。
​
TreeSet
TreeSet线程不安全,基于红黑树实现,不允许null值存在,可以对元素进行自然排序或自定义排序。可以实现元素按照升序进行排序。

常见set的使用场景

HashSet:适用于需要快速查找的场景,不保证元素的顺序。
LinkedHashSet:适用于需要保持元素插入顺序的场景。
TreeSet:适用于需要元素排序的场景。

HashSet如何实现线程安全?

使用Collections.synchronizedSet
Java 提供了一个简单的方法来创建一个同步的集合,通过Collections.synchronizedSet方法。这个方法返回一个线程安全的集合包装器。使用这个方法后,所有对集合的访问都将是同步的。
​
使用ConcurrentHashMap
如果需要更高效的并发访问,可以使用ConcurrentHashMap来实现类似HashSet的功能。
​
手动同步
如果你不想使用上述任何一种方法,也可以手动同步HashSet的访问。可以使用synchronized关键字来保护对HashSet的访问

介绍一下HashMap?

HashMap主要是用于存储键值对。基于哈希表实现,提供了快速的插入、删除和查找操作,线程不安全的,允许一个 null 键或多个 null 值。
不记录映射的顺序。
​
主要方法
put(K key, V value):将指定的值与该映射中的指定键关联。
get(Object key):返回指定键所映射的值。
remove(Object key):如果存在一个键的映射,则将其从映射中移除。
size():返回此映射中的键值映射关系的数量。

HashMap怎么计算hashCode的?

HashMap使用键的hashCode()方法来生成哈希值,并对其进行一些处理,以提高哈希表的性能和均匀分布。

生成hashcode为什么要使用扰动函数?

目的:提高哈希码的质量,使其在哈希表中更均匀地分布。
扰动算法的步骤如下:
1. 获取键的哈希码:h = key.hashCode()
2. 右移 16 位:h >>> 16
3. 异或运算:h ^ (h >>> 16)
这种方法通过将高位和低位的哈希码混合在一起,减少了哈希冲突的概率,从而使得哈希码更加均匀地分布在哈希表的桶中。

HashMap的主要参数都有哪些?

初始容量:
初始容量是HashMap在创建时分配的桶数组的大小。默认初始容量是 16。可以在创建HashMap时通过构造函数指定初始容量。
​
负载因子(Load Factor)
负载因子默认负载因子是 0.75,这意味着当HashMap中的条目数达到当前容量的 75% 时,HashMap会进行扩容。负载因子越低,哈希表中的空闲空间越多,冲突越少,但空间利用率也越低。
​
阈值(Threshold)
阈值是HashMap需要扩容的临界点,计算方式为初始容量 * 负载因子。当实际存储的键值对数量超过这个阈值时,HashMap会进行扩容。
​
桶(Bucket)
HashMap内部使用一个数组来存储链表或树(在 Java 8 及之后的版本中,当链表长度超过一定阈值时,会转化为树)。每个数组元素称为一个桶(bucket)。哈希值经过计算后决定了键值对存储在哪个桶中。
​
哈希函数(Hash Function)
HashMap使用哈希函数将键的哈希码转换为数组索引。Java 的HashMap使用了扰动函数(perturbation function)来减少哈希冲突。
​
链表和树(Linked List and Tree)
在桶中的键值对存储方式上,HashMap使用链表来处理哈希冲突。在 Java 8 及之后的版本中,当链表的长度超过阈值(默认是 8)时,链表会转换为红黑树,以提高查找效率。  
​
红黑树转换阈值(Treeify Threshold)
这是一个阈值,当单个桶中的链表长度超过这个值时,链表会转换为红黑树。默认值是 8。
​
扩容因子(Resize Factor)
当HashMap的大小超过阈值时,容量会加倍。即新的容量是旧容量的两倍。
​
迭代器(Iterators)
HashMap提供了键、值和条目的迭代器,用于遍历HashMap中的元素。

为什么hashMap的容量扩容时一定是2的幂次?

在HashMap中,初始化设置长度时,容量自动转成 2 的幂次长度,这样设计有几个重要原因,主要是为了优化性能和简化计算。
​
减少哈希冲突:
哈希冲突发生时,不同的键计算出的索引相同,导致它们被存储在同一个桶中。通过将容量设置为2的幂次,哈希表能够更均匀地分布哈希值,减少冲突。
​
简化扩容
HashMap在需要扩容时,通常会将容量加倍。如果容量总是2的幂次,那么加倍后的容量仍然是2的幂次,这样可以简化扩容过程中的计算和重新哈希操作。
​
内存对齐和效率
计算机内存分配通常更高效地处理 2 的幂次大小的内存块。使用 2 的幂次长度可以更好地利用内存对齐,提高内存访问效率。

解决hash碰撞的方法?

链地址法(Chaining)
在这种方法中,每个桶(bucket)包含一个链表。当发生哈希碰撞时,新的键值对被添加到相应桶的链表中。
​
线性探测(Linear Probing)
当发生哈希碰撞时,线性探测法在哈希表中向后依次查找下一个空闲位置。
​
二次探测(Quadratic Probing)
二次探测法在发生哈希碰撞时,按照平方序列查找空闲位置(如 1, 4, 9, 16, ...)。
​
双重散列(Double Hashing)
双重散列法使用两个不同的哈希函数。当第一个哈希函数发生碰撞时,使用第二个哈希函数计算新的索引。
​
再哈希法(Rehashing)
再哈希法在发生碰撞时,使用不同的哈希函数重新计算哈希值,直到找到空闲位置。

HashMap的负载因子初始值为什么是0.75?

HashMap的负载因子(load factor)初始值设为 0.75 是一个经过权衡的结果,主要考虑了性能和内存使用之间的平衡。

HashMap,扩容过程?怎么解决哈希冲突?

HashMap 扩容过程
1. 当添加元素时,如果数组为空,会进行初始化:默认情况下,会创建一个长度为 16 的数组,并且加载因子默认为 0.75。
2. 当数组中的元素数量大于或等于数组长度与加载因子的乘积时:例如,当数组长度为16,加载因子为0.75,并且元素数量达到12时(16*0.75 = 12),会触发扩容。扩容时,数组长度会翻倍(通常是2的幂),并重新哈希所有元素到新的数组中。
​
哈希冲突解决
1. 链表法(链表或红黑树):在 HashMap 中,每个位置(索引)可以存储一个链表(或红黑树,当链表长度超过一定阈值时)。当发生哈希冲突时,新的元素会被添加到对应的链表中。在 Java 8 及之后的版本中,当链表长度达到 8 且数组长度大于 64 时,链表会转换为红黑树以优化性能。
2. 哈希函数:为了降低哈希冲突的概率,HashMap 使用了一个哈希函数来计算键的哈希值。这个哈希函数考虑了键对象的哈希码以及键在数组中的索引位置,通过一些位运算得到最终的哈希值。这样可以确保哈希值的分布尽可能均匀,减少冲突的可能性。
3. 初始容量和加载因子:初始容量和加载因子也会影响哈希冲突的概率。较大的初始容量和较小的加载因子可以降低哈希冲突的概率,但也会增加空间开销。因此,在选择这些参数时需要根据具体需求进行权衡。

为什么hashmap多线程会进入死循环?

1、并发修改导致的链表环
当两个或多个线程同时修改HashMap,例如在同一个桶中插入元素,可能会导致链表的指针被错误地更新。
​
2、扩容导致的并发问题
HashMap在容量达到一定阈值时会进行扩容,即重新分配桶数组,并重新哈希所有键值对。如果在扩容过程中,有其他线程同时进行插入操作,可能会导致重新哈希过程中的数据不一致,进而引发死循环。
​
3、解决方案  
使用线程安全的数据结构,在多线程环境中,使用ConcurrentHashMap代替HashMap。ConcurrentHashMap通过分段锁机制来保证线程安全,并发性能更好。

什么是HashTable?

Hashtable很多映射的常用功能与 HashMap类似,不同的是它承自 Dictionary 类,单线程并且是线程安全的。日常不建议使用。

什么是LinkedHashMap?

1. 有序性:LinkedHashMap保证了键值对的顺序,可以是插入顺序(默认)或访问顺序(可选)。
2. 哈希表和链表结合:LinkedHashMap通过哈希表实现快速的键值对查找,同时通过双向链表维护顺序。
3. 允许null键和值:LinkedHashMap允许一个null键和多个null值。
4. 线程不安全:LinkedHashMap不是线程安全的,如果需要在多线程环境中使用,需要通过外部同步机制来保证线程安全。

linkedHashMap为什么能用来做LRUCache(缓存)?

LinkedHashMap 能用来做 LRU 缓存的关键原因在于它可以维护访问顺序,并且通过重写removeEldestEntry方法,可以轻松实现缓存的自动清理。
​
实现 LRU 缓存的步骤
1. 创建一个LinkedHashMap实例,并将accessOrder参数设置为true。
2. 重写removeEldestEntry方法,以便在缓存大小超过预定义的最大容量时自动移除最老的键值对。

linkedhashmap如何保证有序性?

1. 双向链表:LinkedHashMap在内部维护了一个双向链表。每个节点对应一个键值对,并且包含指向前一个节点和后一个节点的引用。通过这个链表,LinkedHashMap可以快速地遍历所有键值对,保持其有序性。
2. 插入顺序:默认情况下,LinkedHashMap按照键值对插入的顺序来维护顺序。每次插入新键值对时,它会将新节点添加到链表的末尾。
3. 访问顺序:如果在构造方法中将accessOrder参数设置为true,LinkedHashMap将按照访问顺序来维护键值对的顺序。每次访问(get或put操作)一个键值对时,它会将对应的节点移动到链表的末尾。

什么是fail-fast机制?

在Java集合框架中,fail-fast是一种机制,用于检测在遍历集合时的结构性修改,并立即抛出异常以防止不一致状态。fail-fast迭代器在检测到集合在迭代过程中被修改后,会抛出ConcurrentModificationException异常。

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

windows工具 -- 使用rustdesk和云服务器自建远程桌面服务, 手机, PC, Mac, Linux远程桌面 (简洁明了)

目的 向日葵最先放弃了, todesk某些功能需要收费, 不想用了想要 自己搭建远程桌面 自己使用希望可以电脑 控制手机分辨率高一些 原理理解 ubuntu云服务器配置 够买好自己的云服务器, 安装 Ubuntu操作系统 点击下载 hbbr 和 hbbs 两个 deb文件: https://github.com/rustdesk/…

GIC寄存器介绍

往期内容 本专栏往期内容,interrtupr子系统: 深入解析Linux内核中断管理:从IRQ描述符到irq domain的设计与实现Linux内核中IRQ Domain的结构、操作及映射机制详解中断描述符irq_desc成员详解Linux 内核中断描述符 (irq_desc) 的初始化与动态分…

排序算法 - 冒泡

文章目录 1. 冒泡排序1.1 简介1.2 基本步骤:1.3 示例代码(C)1.4 复杂度分析1.5 动画展示 1. 冒泡排序 1.1 简介 冒泡排序(Bubble Sort)是一种简单的排序算法,其基本思想是通过相邻元素的比较和交换&#…

【机器学习】机器学习中用到的高等数学知识-2.概率论与统计 (Probability and Statistics)

概率分布:理解数据的分布特征(如正态分布、伯努利分布、均匀分布等)。期望和方差:描述随机变量的中心位置和离散程度。贝叶斯定理:用于推断和分类中的后验概率计算。假设检验:评估模型的性能和数据显著性。…

解决虚拟机未被自动分配ip

文章目录 1. 背景2. 解决步骤 1. 背景 从vulnhub下载的靶场文件,网络适配器模式设置为nat模式之后,启动虚拟机之后发现没有成功分配动态ip。推测是虚拟机分配的网卡名称和原先靶机作者设置网络配置文件 网络接口名称不一致导致。 2. 解决步骤 解决办法就…

人力资源招聘系统的革新之路:从传统到智能的转变

在全球化与数字化交织的今天,企业间的竞争日益激烈,而人才作为企业发展的核心驱动力,其重要性不言而喻。传统的人力资源招聘方式,如依赖纸质简历、人工筛选、面对面面试等,不仅效率低下,且难以精准匹配企业…

vue3入门和实战-vue3项目实现网址导航效果

文章目录 前言一、静态文件引入1. 下载webstack代码2. css调整3. js文件调整4.json数据文件二、项目布局和文件布局调整src/router/index.tssrc/views/Layout/LayoutIndex.vuesrc/views/Layout/IndexComponents/LayoutLeft.vuesrc/views/Home/Home.vuesrc/views/Home/component…

释放 PWA 的力量:2024 年的现代Web应用|React + TypeScript 示例

在2024年的Web开发领域,PWA(Progressive Web Apps)已经成为一个不可忽视的技术趋势。这篇文章将探讨PWA的最新发展,并通过实例展示如何构建一个现代PWA应用。 PWA的本质与优势 PWA本质上是一种将Web应用提升到接近原生应用体验的技…

el-form el-table 前端排序+校验+行编辑

一、页面 <template><div class"bg" v-if"formData.mouldData?.length 0">当前暂无模板&#xff0c;点击<view class"add" click"addMould">立即创建</view></div><div v-else><el-col :x…

ERA5下载数据-U850

ERA5更新后&#xff1a; 1. 升级新的cdsapirc Catalogue — 气候数据存储 --- Catalogue — Climate Data Store (copernicus.eu) ERA5下载数据页面&#xff0c;选择&#xff08;不是这个…………&#xff09; 是这个&#xff1a; ERA5 hourly data on pressure levels from…

分享 pdf 转 word 的免费平台

背景 找了很多 pdf 转 word 的平台都骗进去要会员&#xff0c;终于找到一个真正免费的&#xff0c;遂分享。 网址 PDF转Word转换器 - 100%免费市面上最优质的PDF转Word转换器 - 免费且易于使用。无附加水印 - 快速将PDF转成Word。https://smallpdf.com/cn/pdf-to-word

【Java入门 - 分支结构】第2关:if语句测试题

Java 中的 if 语句&#xff1a;灵活控制程序流程的利器 在 Java 编程中&#xff0c;if语句是一种基本但极其重要的控制结构&#xff0c;它允许我们根据特定的条件来决定程序的执行路径。本文将深入探讨 Java 中的if语句&#xff0c;介绍其语法、用法和一些常见的应用场景。 一…

iOS 18.1,未公开的新功能

童锦程祖师爷曾说过&#xff1a;“发誓可以&#xff0c;发朋友圈不行。”表面上看是渣男语录&#xff0c;实际上也说明了人们对隐私的看重。 在当今生活中&#xff0c;智能手机可能是最私密的电子产品&#xff0c;没有之一。不管是照片、联系人、短信、APP数据&#xff0c;甚至…

06.VSCODE:备战大项目,CMake专项配置

娇小灵活的简捷配置不过是年轻人谈情说爱的玩具&#xff0c;帝国大厦的构建&#xff0c;终归要交给CMake去母仪天下。一个没有使用 CMake 的 C 项目&#xff0c;就像未来世界里的一台相声表演&#xff0c;有了德纲却无谦&#xff0c;观众笑着遗憾。—— 语出《双城记》作者&…

基于 CentOS7.6 的 Docker 下载常用的容器(MySQLRedisMongoDB),解决拉取容器镜像失败问题

安装MySQL&Redis&MongoDB mysql选择是8版本&#xff0c;redis是选择4版本、mongoDB选择最新版&#xff0c;也可以根据自己的需要进行下载对应的版本&#xff0c;无非就是容器名:版本号 这样去拉去相关的容器镜像。如果你还不会在服务器中安装 docker&#xff0c;可以查…

Sping全面复习

Spring框架是一个功能强大且广泛使用的Java平台&#xff0c;它通过提供全面的基础设施支持&#xff0c;使得开发人员能够轻松构建高效、可移植、易于测试的代码。Spring的核心特性包括依赖注入&#xff08;DI&#xff09;、面向切面编程&#xff08;AOP&#xff09;和事件驱动模…

【Linux学习】【Ubuntu入门】1-3 ubuntu连接USB设备

1.打开VMware&#xff0c;打开新建的虚拟机&#xff0c;插入U盘&#xff0c;可在弹出对话框进行选择USB连接到主机或连接到虚拟机。&#xff08;长时间未操作默认连接主机&#xff09; 2.若USB在连接主机的情况下&#xff0c;可通过右键点击右下角进行连接到虚拟机。 3.若已连接…

炼码LintCode--数据库--基础语法--刷题笔记_01

目录 炼码LintCode数据库入门级别的笔记未完待续~~~ 炼码LintCode 数据库 入门级别的笔记 笔记如下&#xff0c;把所有涉及到的入门级别的知识点简单总结了一下。 以及一点点举一反三的写法。 增 INSERT INTO 表名 (列1, 列2, ...) VALUES (值1, 值2, ...);批量增 INSERT INT…

docker:docker: Get https://registry-1.docker.io/v2/: net/http: request canceled

无数次的拉镜像让人崩溃&#xff1a; rootnode11:~/ragflow/docker# more rag.sh #export HTTP_PROXYhttp://192.168.207.127:7890 #export HTTPS_PROXYhttp://192.168.207.127:7890 #export NO_PROXYlocalhost,127.0.0.1,.aliyun.com docker compose -f docker-compose-gpu-C…

Flutter:使用Future发送网络请求

pubspec.yaml配置http的SDK cupertino_icons: ^1.0.8 http: ^1.2.2请求数据的格式转换 // Map 转 json final chat {name: 张三,message: 吃饭了吗, }; final chatJson json.encode(chat); print(chatJson);// json转Map final newChat json.decode(chatJson); print(newCha…