Java数据结构面试题(一)

目录

一.ArrayList和LinkedList的区别

二.ArrayList和Vector的区别

三.HashMap的底层实现

四.HashMap和ConcurrentHashMap的区别

五.HashMap和HashTable的区别

六.多线程的情况下使用HashMap呢?

七.HashMap的如何扩容呢?

八.哈希冲突


 

本专栏全是博主自己收集的面试题,仅可参考,不能相信面试官就出这种题目。

 

一.ArrayList和LinkedList的区别

实现,ArrayList 和 LinkedList 都是 Java 中的 List 接口的实现类。

不同点:

  1. 它们的底层实现不同:ArrayList 是基于动态数组的数据结构,而 LinkedList 是基于链表的数据结构。
  2. 随机访问性能不同:ArrayList 优于 LinkedList,因为 ArrayList 可以根据下标以 O(1) 时间复杂度对元素进行随机访问。而 LinkedList 的访问时间复杂度为 O(n),因为它需要遍历整个链表才能找到指定位置的元素。
  3. 插入和删除性能不同:LinkedList 优于 ArrayList,因为 LinkedList 的插入和删除操作时间复杂度为 O(1),而 ArrayList 的时间复杂度为 O(n)。

单独针对ArrayList的解析

         初始化时可以指定初始容量的大小,默认为10,扩容机制:增加当前容量的 50%。

二.ArrayList和Vector的区别

        ArrayList 和 Vector 实现了 List 接口,它们都是动态数组的实现,使用方法也是一样,但是也有不同的地方

  • 线程安全性:Vector 是线程安全的,而 ArrayList 不是。所以在多线程环境下,应该使用 Vector。
  • 性能:由于 Vector 是线程安全的,所以它的性能通常比 ArrayList 差。在单线程环境下,ArrayList 比 Vector 快。
  • 初始容量增长方式:当容量不足时,ArrayList 默认会增加 50% 的容量,而 Vector 会将容量翻倍。这意味着在添加元素时,ArrayList 需要更频繁地进行扩容操作,而 Vector 则更适合于存储大量数据。

三.HashMap的底层实现

        在jdk1.7版本之前,HashMap的底层设计通过数组 + 链表实现的,而jdk1.8版本之后,HashMap 底层是通过数组 + 链表或红黑树实现的。

详细解析:在jdk 8 中,当链表达到阈值8时,会自动转化为红黑树!这个优化的目的是为了在哈希冲突较严重时,仍然能够保持较快的查询性能,因为红黑树的查找、插入和删除操作的时间复杂度为 O(log n),相比于链表的 O(n) 更加高效。

         当红黑树的节点小于等于 6 时,为了节省内存空间会将红黑树退化为链表

四.HashMap和ConcurrentHashMap的区别

        HashMap 是 Java 中常用的一种基于哈希表实现的数据结构,用于存储键值对。它提供了快速的插入、删除和查找操作,适用于需要频繁操作的场景。

       ConcurrentHashMap 是 Java 中线程安全的哈希表实现,专为高并发场景设计。它提供了比 HashMap 更好的并发性能,同时保持了类似的接口和功能。

两者之间的对比:

  1. 线程安全上:HashMap是不安全的,但是 ConcurrentHashMap是安全的。
  2. 键值对上:HashMap是允许存在null键和null值的,但 ConcurrentHashMap不允许
  3. 性能表现上:在单线程环境当中,HashMap性能高,因为HashMap不需要额外的控制开销,而ConcurrentHashMap 在多线程并发访问时通常表现更好,特别是在读多写少的场景下,由于其分段锁设计能够显著减少线程之间的竞争,提高并发度,从而提升性能。
  4. 迭代方面:HashMap 的迭代器是快速失败的(迭代过程中不允许结构发生改变),ConcurrentHashMap 的迭代器是弱一致的(可以发生改变,但是不保证获取最新的修改)
  5. 初始化:HashMap 在初始化时可以指定初始容量和负载因子,用于优化性能;ConcurrentHashMap 也可以初始化时指定初始容量和负载因子,但不需要考虑并发情况下的扩容问题,因为它使用了分段锁来管理并发。

扩展问题:ConcurrentHashMap 为什么不能插入null键值对?

解析:从Java8版本之后就可以插入null键了,最开始不能插入的原因是:

        如果允许键为 null,ConcurrentHashMap 内部的哈希算法可能会将 null 的哈希值映射到某个有效的 Segment 或桶位上,这样会导致无法确定存储位置,或者在其他操作中造成错误。

        如果值为 null,其他线程可能无法准确判断是键不存在还是键对应的值为 null,这会增加实现的复杂性和不确定性。

五.HashMap和HashTable的区别

        HashMap 和 Hashtable 都实现了 Map 接口,都是 Java 中用于存储键值对的数据结构,它们的底层数据结构都是数组加链表的形式。但即使如此也存在几点不同:

解析:为什么HashTable不允许存储null键和值,是因为它的key值进行哈希计算,如果为null的话,无法调用该方法,还是会抛出空指针异常,而值为null的话,HashTable源码会主动抛出异常。

  1. 线程安全:Hashtable 是线程安全的,而 HashMap 是非线程安全的。
  2. 性能:因为 Hashtable 使用了 synchronized 给整个方法添加了锁,所以相比于 HashMap 来说,它的性能不如 HashMap。
  3. 存储:HashMap 允许 key 和 value 为 null,而 Hashtable 不允许存储 null 键和 null 值。

HashMap 允许 key 和 value 为 null 的原因是因为在 HashMap 中对 null 值进行了特殊处理,如果为 null 时会把它赋值为 0。

扩展知识:Hashtable 不推荐使用,即使线程安全,也不推荐使用,因为整个方法添加 synchronized 来实现线程安全的,所以它的性能很差。而推荐的是ConcurrentHashMap,性能高。

六.多线程的情况下使用HashMap呢?

        HashMap是不安全的,可是有些面试官就是搞事情,说我就要用,你就说怎么搞吧!

在多线程的情况下,使用HashMap的方法:

        使用 Collections.synchronizedMap() 包装

Map<K, V> synchronizedMap = Collections.synchronizedMap(new HashMap<>());

缺点:并发的性能很低

七.HashMap的如何扩容呢?

        说起HashMap,我们可以了解一下它的底层原理,由数组+链表组建,而扩容则是扩容数组,当 元素个数 > 容量*负载因子 时,就会进行扩容,而默认的负载因子:0.75,初始容量可以调节,默认是16.

或许面试官会追问:为什么不是满了之后再扩容呢?

答:哈希表不像其他的数据容器,它的内部存储数据是有不一样的。元素都会根据键对象的HashCode()方法得到,然后进行一系列的运算,确定键值对在数组当中的位置。

追问:为什么负载因子是0.75呢?怎么不能是0.8、0.6呢?

答:0.75是空间利用率和性能的一个平衡点,可以保证大多数情况下较高的查找效率和插入效率,过高会增加哈希冲突发生的概率,过低会造成存储的元素过少。

八.哈希冲突

元素在存储的过程当中,是怎么样的一个过程呢?

第一步:得到键的哈希值hash

第二步:确定存储位置,方法:(n - 1) & hash  其中的n是数组的长度

第三步:插入键值对,如果确定的存储位置为空,则直接存储,若不为空,则进行查找该存储位置下的链表或者红黑树是否有对应的键值,若有,则更新,若无,则添加在末尾!

第四步:当前元素数量达到了负载因子乘以数组容量的阈值,进行扩容操作,扩容包括创建一个更大的数组,并重新计算所有键值对的存储位置,然后将它们移到新数组中。

哈希冲突,为什么会有哈希冲突呢?

    原因:不同的键可能有相同的哈希码

解决方法:

  1. 链地址法:也就是数组+链表,链表过长转为红黑树
  2. 开放地址法:发生哈希冲突时,通过一定的探测方法(线性探测、二次探测、双重哈希等)在哈希表中寻找下一个可用的位置。这种方法的优点是不需要额外的存储空间,适用于元素数量较少的情况。缺点是容易产生聚集现象,即某些桶中的元素过多,而其他桶中的元素很少。
  3. 再哈希法(Rehashing):当发生哈希冲突时,使用另一个哈希函数计算出一个新的哈希值,然后将元素插入到对应的桶中。这种方法的优点是简单易懂,适用于元素数量较少的情况。缺点是需要额外的哈希函数,且当哈希函数不够随机时,容易产生聚集现象。

扩展知识:线性探测VS二次探测

线性探测:发生哈希冲突时,线性探测会在哈希表中寻找下一个可用的位置,具体来说,它会检查哈希表中下一个位置是否为空,如果为空,则将元素插入该位置;如果不为空,则继续检查下一个位置,直到找到一个空闲的位置为止。

二次探测:如果初始位置已被占用,则使用二次探测序列计算下一个位置,通过二次探测序列,然后依次检查哈希表中的每个位置,直到找到一个空闲的位置为止。二次探测序列通常是一系列平方数的序列,例如 (1^2, 2^2, 3^2, \ldots)。二次探测序列:[ h_i = (hash + c1 \cdot i + c2 \cdot i^2) \mod m ]

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

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

相关文章

Mac/Linux安装JMeter压测工具

Mac安装JMeter压测工具 介绍 Apache JMeter™应用程序是开源软件&#xff0c;是一个100%纯的Java应用程序&#xff0c;旨在加载测试功能行为和衡量性能。它最初是为测试Web应用程序而设计的&#xff0c;但后来扩展到其他测试功能。 我能用它做什么&#xff1f; Apache JMet…

VCL界面组件DevExpress VCL v24.1 - 发布全新的矢量主题

DevExpress VCL是DevExpress公司旗下最老牌的用户界面套包&#xff0c;所包含的控件有&#xff1a;数据录入、图表、数据分析、导航、布局等。该控件能帮助您创建优异的用户体验&#xff0c;提供高影响力的业务解决方案&#xff0c;并利用您现有的VCL技能为未来构建下一代应用程…

起飞,纯本地实时语音转文字!

简介 偶然在 github 上翻到了这个项目 https://github.com/k2-fsa/sherpa-ncnn 在没有互联网连接的情况下使用带有 ncnn 的下一代 Kaldi 进行实时语音识别。支持 iOS、Android、Raspberry Pi、VisionFive2、LicheePi4A等。 也就是说语音转文字可以不再借助网络服务的接口&am…

桂花网蓝牙网关X1000:引领物联网新时代的智能连接

在物联网技术飞速发展的今天&#xff0c;蓝牙网关作为连接蓝牙设备与互联网的关键设备&#xff0c;其性能与稳定性直接影响到物联网系统的整体运行效果。桂花网蓝牙网关X1000凭借其卓越的性能和广泛的应用场景&#xff0c;成为了物联网领域的佼佼者。 一、产品概述 桂花网蓝牙…

fastadmin最新版导出数据时 表格中会有 html标签的解决办法

fastadmin 自带的导出方法, 是一个纯前端的导出, 没有请求后台的接口 当我们使用导出功能时, 有些数据, 我们在设计的时候,配置的是 枚举类型的 但是当我们导出数据的时候, 居然导出的数据中带有 html 的标签 上面的情况我们的解决办法是,在导出的时候,把html 的标签…

mongdb学习与使用

1. 基础概念 MongoDB简介&#xff1a; MongoDB是一个基于文档的NoSQL数据库&#xff0c;具有高性能、高可用性和易扩展性。数据存储在类似JSON的BSON格式中。 基本术语&#xff1a; Database&#xff08;数据库&#xff09;&#xff1a; 集合的容器。Collection&#xff08;集合…

C++必修:深入理解继承与虚继承

✨✨ 欢迎大家来到贝蒂大讲堂✨✨ &#x1f388;&#x1f388;养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; 所属专栏&#xff1a;C学习 贝蒂的主页&#xff1a;Betty’s blog 1. 继承的概念与定义 1.1. 继承的概念 继承(inheritance)机制是面向对象程序设计…

每日一题——Python实现PAT乙级1018 锤子剪刀布(举一反三+思想解读+逐步优化)五千字好文

一个认为一切根源都是“自己不够强”的INTJ 个人主页&#xff1a;用哲学编程-CSDN博客专栏&#xff1a;每日一题——举一反三Python编程学习Python内置函数 Python-3.12.0文档解读 目录 我的写法 代码结构与逻辑 时间复杂度分析 空间复杂度分析 代码优化建议 总结 我…

【java计算机毕设】美容院管理系统 项目源代码MySQL springboot vue html maven+文档 前后端可分离也可不分离

目录 1项目功能 2项目介绍 3项目地址 1项目功能 【java计算机毕设】美容院管理系统 项目源代码MySQL springboot vue html maven文档 前后端可分离也可不分离 2项目介绍 系统功能&#xff1a; 美容院管理系统包括管理员、用户俩种角色。 管理员功能包括个人中心模块用于修改…

“论单元测试方法及应用”精选范文,软考高级论文,系统架构设计师论文

论文真题 1、概要叙述你参与管理和开发的软件项目,以吸你所担的主要工作。 2、结给你参与管理和开发的软件项目&#xff0c;简要叙述单元测试中静态测试和动态测试方法的基本内容。 3、结给你惨与管理和研发的软件项目,体阐述在玩测试过程中,如何确定白盒测试的覆盖标准,及如…

【C语言】sizeof 关键字

在C语言中&#xff0c;sizeof运算符用于计算数据类型或变量的大小&#xff08;以字节为单位&#xff09;。sizeof是一个编译时运算符&#xff0c;它在编译阶段确定类型或变量的大小&#xff0c;而不是在运行时。 基本用法 sizeof可以用于计算基本数据类型、数组、结构体以及指…

银湖资本与UIBE达成战略合作,共同推动股权投资领域发展

近日&#xff0c;全球知名私募股权投资公司银湖资本&#xff08;Silver Lake Partners&#xff09;宣布与对外经济贸易大学&#xff08;UIBE&#xff09;校友发起的“UIBE阿波罗股权投资俱乐部”达成战略合作协议。此举不仅标志着双方在股权投资领域的深度合作&#xff0c;也为…

LVS-DR负载均衡

LVS-DR负载均衡 LVS—DR工作模式 原理 客户端访问调度器的VIP地址&#xff0c;在路由器上应该设置VIP跟调度器的一对一的映射关系&#xff0c;调度器根据调度算法将该请求“调度“到后端真实服务器&#xff0c;真实服务器处理完毕后直接将处理后的应答报文发送给路由器&#xf…

使用 draw.io 画图

尽管我非常喜欢 wps 和 office 的 ppt 画图&#xff0c;但因为它们对数学公式的糟糕支持&#xff0c;我不得不另外寻找一个画图工具。当然我也同样很喜欢 visio &#xff0c;但同样的&#xff0c;它对数学公式的支持糟糕&#xff0c;另外&#xff0c;最为重要的是&#xff0c;v…

不同的llm推理框架

vLLM适用于大批量Prompt输入&#xff0c;并对推理速度要求比较高的场景。 实际应用场景中&#xff0c;TensorRT-LLM通常与Triton Inference Server结合起来使用&#xff0c;NVIDIA官方能够提供更适合NVIDIA GPU运行的高效Kernel。 LightLLM比较轻量、易于扩展、易于上手&…

Android 抓取 CPU 资源信息

在 Android 开发中&#xff0c;使用 ADB&#xff08;Android Debug Bridge&#xff09;命令获取 CPU 资源信息有很多重要的作用。这些命令可以帮助开发者在多种情况下分析和优化应用性能、解决问题以及进行系统性调试。 以下列举一些 ABD 获取 CPU 资源信息的命令 获取 CPU 核…

农作物生长环境的远程监控与智能调控

农作物生长环境的远程监控与智能调控 农作物生长环境的远程监控与智能调控技术&#xff0c;作为现代农业科技的核心组成部分&#xff0c;正逐步革新传统农业的生产模式&#xff0c;推动农业向精准化、智能化转型。这一技术体系综合应用了物联网、大数据、云计算以及人工智能等…

C语言实战 | Flappy Bird游戏

Flappy Bird游戏是由一名越南游戏制作者独自开发的&#xff0c;曾经风靡全球。游戏规则非常简单&#xff0c;玩家必须控制一只小鸟&#xff0c;跨越由各种长度的水管所组成的障碍物&#xff0c;如果撞上管道游戏就结束&#xff0c;如图11.11所示。 ■ 图11.11Flappy Bird 游戏 …

启明智显Model3A芯片方案7寸高清触摸屏ZX7D00CM21S:开箱、设置与实操全攻略指南

一、背景 本指南将详细介绍启明智显的Model3A芯片方案下的7寸高清触摸屏ZX7D00CM21S的开箱步骤、基础设置以及实操应用。无论您是电子爱好者、开发者还是工程师&#xff0c;这份指南都能助您快速上手并充分利用这款触摸屏的各项功能。 二、硬件介绍 ZX7D00CM21S 7寸高清触摸屏是…

不知几DAY的Symfony---RCE复现

感谢红队大佬老流氓的供稿&#xff0c;此篇文章是针对Symfony框架的一个RCE漏洞复现 ​框架简介 Symfony是一个开源的PHP Web框架&#xff0c;它现在是许多知名 CMS 的核心组件&#xff0c;例如Drupal、Joomla!、eZPlatform&#xff08;以前称为 eZPublish&#xff09;或Bolt。…