JAVA面试八股文之集合

news/2024/4/29 13:19:23/文章来源:https://blog.csdn.net/m0_59230408/article/details/134916660

JAVA集合相关

  • 集合?
  • 说一说Java提供的常见集合?
  • hashmap的key可以为null嘛?
  • hashMap线程是否安全, 如果不安全, 如何解决?
  • HashSet和TreeSet?
  • ArrayList底层是如何实现的?
  • ArrayList list=new ArrayList(10)中的list扩容几次
  • 如何实现数组和List之间的转换
  • 用Arrays.asList转List后,如果修改了数组内容,list受影响吗?List用toArray转数组后,如果修改了List内容,数组受影响吗?
  • ArrayList 和 LinkedList 的区别是什么?
  • ArrayList 和 LinkedList 不是线程安全的,你们在项目中是如何解决这个的线程安全问题的?
  • 说一下HashMap的实现原理?
  • HashMap的jdk1.7和jdk1.8有什么区别?
  • 你能说下HashMap的put方法的具体流程吗?
  • 讲一讲HashMap的扩容机制吗?
  • 通过hash计算后找到数组的下标,是如何找到的呢,你了解hashMap的寻址算法吗?
  • 为何HashMap的数组长度一定是2的次幂?
  • 你知道hashmap在1.7情况下的多线程死循环问题吗?
  • hashmap是线程安全的吗?
  • 那我们想要使用线程安全的map该怎么做呢?
  • 那你能聊一下ConcurrentHashMap的原理吗?
  • HashSet与HashMap的区别?
  • HashTable与HashMap的区别?

集合?

Collection接口:

​ List接口: 里面的数据有序, 可以重复

  • ArrayList实现类: 底层使用数组实现, 线程不安全

  • LinkedList实现类: 底层使用链表实现, 线程不安全,

  • Vector实现类 : 底层使用数组实现, 速度慢, 因为线程安全(底层使用重量级锁实现的线程安全)

Set接口: 里面的数据无序不可以重复

  • HashSet实现类: 底层使用哈希表存储, 数据无序且唯一

  • treeSet实现类: 底层采用有序二叉树进行存储, 自然排序.

Map接口: 里面的数据是key, value键值对格式, 属于hash表格式.

  • HashMap实现类: 底层使用哈希表存储数据, key可以为null, 线程不安全

  • TreeMap实现类: 底层使用红黑树实现.

  • HashTable实现类: 底层使用哈希表实现, key不可以为null, 线程安全.

说一说Java提供的常见集合?

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

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

  • 在Collection中有两个子接口List和Set。在我们平常开发的过程中用的比较多像list接口中的实现类ArrarList和LinkedList。 在Set接口中有实现类HashSet和TreeSet。
  • 在map接口中有很多的实现类,平时比较常见的是HashMap、TreeMap,还有一个线程安全的map:ConcurrentHashMap

hashmap的key可以为null嘛?

hashmap的key可以为null(hashMap中使用hash()方法来计算key的哈希值,当key为空时,直接令key的哈希值为0,不走key.hashCode()方法;)
hashTable不允许key值为空:问题出在int hash = key.hashCode()这里,当key为null时,key.hashCode()会报空指针异常。

hashMap线程是否安全, 如果不安全, 如何解决?

hashMap线程是不安全的.

hashmap可以通过加锁保证线程安全, 按照速度由慢到快, 可以使用

重量级锁(慢), 也就是同步代码块或者同步方法来解决

加轻量级锁(稍快), lock接口, lock接口中可以使用RetreenLock或者ReadWriteLock读写锁.

使用concurrentHashMap来替代加锁, concurrentHashMap底层是无锁的, 但是可以保证线程安全, 因为底层使用了CAS内存比较交换技术实现.

HashSet和TreeSet?

  • 元素,无序、不可重复

ArrayList底层是如何实现的?

我阅读过arraylist的源码,我主要说一下add方法吧

第一:确保数组已使用长度(size)加1之后足够存下下一个数据

第二:计算数组的容量,如果当前数组已使用长度+1后的大于当前的数组长度,则调用grow方法扩容(原来的1.5倍)

第三:确保新增的数据有地方存储之后,则将新元素添加到位于size的位置上。

第四:返回添加成功布尔值。

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

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

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

数组转list,可以使用jdk自动的一个工具类Arrars,里面有一个asList方法可以转换为数组
List 转数组,可以直接调用list中的toArray方法,需要给一个参数,指定数组的类型,需要指定数组的长度。

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

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

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

ArrayList 和 LinkedList 的区别是什么?

它们两个主要是底层使用的数据结构不一样,ArrayList 是动态数组,LinkedList 是双向链表,这也导致了它们很多不同的特点。

1,从操作数据效率来说

ArrayList按照下标查询的时间复杂度O(1)【内存是连续的,根据寻址公式】, LinkedList不支持下标查询

查找(未知索引): ArrayList需要遍历,链表也需要链表,时间复杂度都是O(n)

新增和删除

  • ArrayList尾部插入和删除,时间复杂度是O(1);其他部分增删需要挪动数组,时间复杂度是O(n)
  • LinkedList头尾节点增删时间复杂度是O(1),其他都需要遍历链表,时间复杂度是O(n)

2,从内存空间占用来说

ArrayList底层是数组,内存连续,节省内存

LinkedList 是双向链表需要存储数据,和两个指针,更占用内存

3,从线程安全来说,ArrayList和LinkedList都不是线程安全的

ArrayList 和 LinkedList 不是线程安全的,你们在项目中是如何解决这个的线程安全问题的?

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

第二:如果非要在成员变量中使用的话,可以使用线程安全的集合来替代

ArrayList可以通过Collections 的 synchronizedList 方法将 ArrayList 转换成线程安全的容器后再使用。

LinkedList 换成ConcurrentLinkedQueue来使用

说一下HashMap的实现原理?

1,底层使用hash表数据结构,即数组+(链表 | 红黑树)

2,添加数据时,计算key的值确定元素在数组中的下标,key相同则替换,不同则存入链表或红黑树中

3,获取数据通过key的hash计算数组下标获取元素

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

  • JDK1.8之前采用的拉链法,数组+链表
  • JDK1.8之后采用数组+链表+红黑树,链表长度大于8且数组长度大于64则会从链表转化为红黑树

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

  1. 判断键值对数组table是否为空或为null,否则执行resize()进行扩容(初始化)

  2. 根据键值key计算hash值得到数组索引

  3. 判断table[i]==null,条件成立,直接新建节点添加

  4. 如果table[i]==null ,不成立
    4.1 判断table[i]的首个元素是否和key一样,如果相同直接覆盖value
    4.2 判断table[i] 是否为treeNode,即table[i] 是否是红黑树,如果是红黑树,则直接在树中插入键值对
    4.3 遍历table[i],链表的尾部插入数据,然后判断链表长度是否大于8,大于8的话把链表转换为红黑树,在红黑树中执行插入操 作,遍历过程中若发现key已经存在直接覆盖value

  5. 插入成功后,判断实际存在的键值对数量size是否超多了最大容量threshold(数组长度*0.75),如果超过,进行扩容。

讲一讲HashMap的扩容机制吗?

  • 在添加元素或初始化的时候需要调用resize方法进行扩容,第一次添加数据初始化数组长度为16,以后每次每次扩容都是达到了扩容阈值(数组长度 * 0.75)

  • 每次扩容的时候,都是扩容之前容量的2倍;

  • 扩容之后,会新创建一个数组,需要把老数组中的数据挪动到新的数组中

  • 没有hash冲突的节点,则直接使用 e.hash & (newCap - 1) 计算新数组的索引位置

  • 如果是红黑树,走红黑树的添加

  • 如果是链表,则需要遍历链表,可能需要拆分链表,判断(e.hash & oldCap)是否为0,该元素的位置要么停留在原始位置,要么移动到原始位置+增加的数组大小这个位置上

通过hash计算后找到数组的下标,是如何找到的呢,你了解hashMap的寻址算法吗?

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

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

为何HashMap的数组长度一定是2的次幂?

第一:

计算索引时效率更高:如果是 2 的 n 次幂可以使用位与运算代替取模

第二:

扩容时重新计算索引效率更高:在进行扩容是会进行判断 hash值按位与运算旧数组长租是否 == 0

如果等于0,则把元素留在原来位置 ,否则新位置是等于旧位置的下标+旧数组长度

你知道hashmap在1.7情况下的多线程死循环问题吗?

jdk7的的数据结构是:数组+链表

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

比如说,现在有两个线程

线程一:读取到当前的hashmap数据,数据中一个链表,在准备扩容时,线程二介入

线程二也读取hashmap,直接进行扩容。因为是头插法,链表的顺序会进行颠倒过来。比如原来的顺序是AB,扩容后的顺序是BA,线程二执行结束。

当线程一再继续执行的时候就会出现死循环的问题。

线程一先将A移入新的链表,再将B插入到链头,由于另外一个线程的原因,B的next指向了A,所以B->A->B,形成循环。

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

hashmap是线程安全的吗?

不是线程安全的

那我们想要使用线程安全的map该怎么做呢?

我们可以采用ConcurrentHashMap进行使用,它是一个线程安全的HashMap

那你能聊一下ConcurrentHashMap的原理吗?

ConcurrentHashMap 是一种线程安全的高效Map集合,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不冲 突,就不会产生并发 , 效率得到提升。

HashSet与HashMap的区别?

(1)HashSet实现了Set接口, 仅存储对象; HashMap实现了 Map接口, 存储的是键值对.

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

HashTable与HashMap的区别?

第一,数据结构不一样,hashtable是数组+链表,hashmap在1.8之后改为了数组+链表+红黑树

第二,hashtable存储数据的时候都不能为null,而hashmap是可以的

第三,hash算法不同,hashtable是用本地修饰的hashcode值,而hashmap经常了二次hash

第四,扩容方式不同,hashtable是当前容量翻倍+1,hashmap是当前容量翻倍

第五,hashtable是线程安全的,操作数据的时候加了锁synchronized,hashmap不是线程安全的,效率更高一些

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

区别HashTableHashMap
数据结构数组+链表数组+链表+红黑树
是否可以为nullKey和value都不能为null可以为null
hash算法key的hashCode()二次hash
扩容方式当前容量翻倍 +1当前容量翻倍
线程安全同步(synchronized)的,线程安全非线程安全

后记
👉👉💕💕美好的一天,到此结束,下次继续努力!欲知后续,请看下回分解,写作不易,感谢大家的支持!! 🌹🌹🌹

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

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

相关文章

【计算机网络】第 11、12 问:流量控制和可靠传输机制有哪些?

目录 正文流量控制的基本方法停止-等待流量控制基本原理滑动窗口流量控制基本原理 可靠传输机制1. 停止-等待协议2. 后退 N 帧协议(GBN)3. 选择重传协议(SR) 正文 流量控制涉及对链路上的帧的发送速率的控制,以使接收…

云数据仓库Snowflake论文完整版解读

本文是对于Snowflake论文的一个完整版解读,对于从事大数据数据仓库开发,数据湖开发的读者来说,这是一篇必须要详细了解和阅读的内容,通过全文你会发现整个数据湖设计的起初原因以及从各个维度(架构设计、存算分离、弹性…

FPGA高端项目:解码索尼IMX327 MIPI相机转HDMI输出,提供FPGA开发板+2套工程源码+技术支持

目录 1、前言2、相关方案推荐本博主所有FPGA工程项目-->汇总目录我这里已有的 MIPI 编解码方案 3、本 MIPI CSI-RX IP 介绍4、个人 FPGA高端图像处理开发板简介5、详细设计方案设计原理框图IMX327 及其配置MIPI CSI RX图像 ISP 处理图像缓存HDMI输出工程源码架构 6、工程源码…

fastadmin学习04-一键crud

FastAdmin 默认内置一个 test 表,可根据表字段名、字段类型和字段注释通过一键 CRUD 自动生成。 create table fa_test (id int unsigned auto_increment comment ID primary key,user_id int(10) default 0 null…

吴恩达深度学习笔记:浅层神经网络(Shallow neural networks)3.1-3.5

目录 第一门课:神经网络和深度学习 (Neural Networks and Deep Learning)第三周:浅层神经网络(Shallow neural networks)3.1 神经网络概述(Neural Network Overview)3.2 神经网络的表示(Neural Network Representation…

YOLOv8全网独家改进: 红外小目标 | 注意力改进 | 多膨胀通道精炼(MDCR)模块,红外小目标暴力涨点| 2024年3月最新成果

💡💡💡本文独家改进:多膨胀通道精炼(MDCR)模块,解决目标的大小微小以及红外图像中通常具有复杂的背景的问题点,2024年3月最新成果 💡💡💡红外小目标实现暴力涨点,只有几个像素的小目标识别率大幅度提升 改进结构图如下: 收录 YOLOv8原创自研 https://blog…

Day24 代码随想录(1刷) 回溯

目录 77. 组合 216. 组合总和 III 17. 电话号码的字母组合 给定两个整数 n 和 k,返回范围 [1, n] 中所有可能的 k 个数的组合。 你可以按 任何顺序 返回答案。 示例 1: 输入:n 4, k 2 输出: [[2,4],[3,4],[2,3],[1,2],[1,3],[1…

Vue生命周期,从听说到深入理解(全面分析)

每个 Vue 组件实例在创建时都需要经历一系列的初始化步骤,比如设置好数据侦听,编译模板,挂载实例到 DOM,以及在数据改变时更新 DOM。在此过程中,它也会运行被称为生命周期钩子的函数,让开发者有机会在特定阶…

基于深度学习的OCR,如何解决图像像素差的问题?

基于深度学习的OCR技术在处理图像像素差的问题时确实面临一定的挑战。图像像素差可能导致OCR系统无法准确识别文本,从而影响其精度和可靠性。尽管已经有一些方法如SRN-Deblur、超分SR和GAN系列被尝试用于解决这个问题,但效果并不理想。然而,这…

论文阅读-Policy Optimization for Continuous Reinforcement Learning

摘要 我们研究了连续时间和空间环境下的强化学习( RL ),其目标是一个具有折扣的无限时域,其动力学由一个随机微分方程驱动。基于连续RL方法的最新进展,我们提出了占用时间(专门针对一个折现目标)的概念,并展示了如何有效地利用它…

【超图 SuperMap3D】【基础API使用示例】51、超图SuperMap3D - 绘制圆|椭圆形面标注并将视角定位过去

前言 引擎下载地址:[添加链接描述](http://support.supermap.com.cn/DownloadCenter/DownloadPage.aspx?id2524) 绘制圆形或者椭圆形效果 核心代码 entity viewer.entities.add({// 圆中心点position: { x: -1405746.5243351874, y: 4988274.8462937465, z: 370…

关于异业联盟模式做成小程序的可行性分析

随着移动互联网的快速发展,小程序作为一种轻量级应用,受到了越来越多企业和用户的青睐。而异业联盟模式则是一种有效的商业合作方式,能够实现资源共享、优势互补和共同发展。将异业联盟模式做成小程序,不仅可以提高用户体验&#…

Pytorch的hook函数

hook函数是勾子函数,用于在不改变原始模型结构的情况下,注入一些新的代码用于调试和检验模型,常见的用法有保留非叶子结点的梯度数据(Pytorch的非叶子节点的梯度数据在计算完毕之后就会被删除,访问的时候会显示为None&…

react-navigation:

我的仓库地址:https://gitee.com/ruanjianbianjing/bj-hybrid react-navigation: 学习文档:https://reactnavigation.org 安装核心包: npm install react-navigation/native 安装react-navigation/native本身依赖的相关包: react-nativ…

时序预测 | Matlab实现SSA-BP麻雀算法优化BP神经网络时间序列预测

时序预测 | Matlab实现SSA-BP麻雀算法优化BP神经网络时间序列预测 目录 时序预测 | Matlab实现SSA-BP麻雀算法优化BP神经网络时间序列预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 1.Matlab实现SSA-BP麻雀算法优化BP神经网络时间序列预测(完整源码和数据…

工业镜头常用参数之实效F(Fno.)和像圈

Fno. 工业镜头中常用到的参数F,有时候用F/#,Fno.来表示,指的是镜头通光能力的参数。它可用镜头焦距及入瞳直径来表示,也可通过镜头数值孔径(NA)和光学放大倍率(β)来计算。有效Fno.…

maven的依赖继承

先说一下创建子maven工程的步骤 继承 继承的作用:在父工程中,统一管理项目中的依赖信息,进行统一的版本控制 继承的背景是:对一个大型的项目进行了模块拆分,一个project下,创建了很多的module&#xff0c…

golang grpc和protobuf的版本降级问题(version4 -> version3)

最后更新于2024年3月28日 10:57:52 简中没查到类似的文章。一点小事闹麻了,搞了一天,特意发出来造福大家。 所谓的版本就是下面这个东西proto.ProtoPackageIsVersion4或者proto.ProtoPackageIsVersion3: 目的 为了适配旧代码&#xff0c…

linux shell命令(进程管理、用户管理)

一、进程的概念 主要有两点: 1.进程是一个实体。每一个进程都有它自己的地址空间,一般情况下,包括文本区域(text region)、数据区域(data region)和堆栈(stack region)…

百度智能小程序源码系统简洁版 SEO关键词排名推广优化 带完整的安装代码包以及搭建教程

移动互联网的快速发展,小程序以其轻量级、无需下载、即用即走的特点,迅速成为了各大平台争相推广的重要产品形态。百度智能小程序作为百度生态下的重要一环,凭借其强大的流量入口和丰富的功能组件,为开发者提供了广阔的创作空间。…