Java集合常见面试题总结(5)

HashSet 如何检查重复?

当你把对象加入HashSet时,HashSet 会先计算对象的hashcode值来判断对象加入的位置,同时也会与其他加入的对象的 hashcode 值作比较,如果没有相符的 hashcodeHashSet 会假设对象没有重复出现。但是如果发现有相同 hashcode 值的对象,这时会调用equals()方法来检查 hashcode 相等的对象是否真的相同。如果两者相同,HashSet 就不会让加入操作成功。

在 JDK1.8 中,HashSetadd()方法只是简单的调用了HashMapput()方法,并且判断了一下返回值以确保是否有重复元素。直接看一下HashSet中的源码:

// Returns: true if this set did not already contain the specified element
// 返回值:当 set 中没有包含 add 的元素时返回真
public boolean add(E e) {return map.put(e, PRESENT)==null;
}

而在HashMapputVal()方法中也能看到如下说明:

// Returns : previous value, or null if none
// 返回值:如果插入位置没有元素返回null,否则返回上一个元素
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,boolean evict) {
...
}

也就是说,在 JDK1.8 中,实际上无论HashSet中是否已经存在了某元素,HashSet都会直接插入,只是会在add()方法的返回值处告诉我们插入前是否存在相同元素。

HashMap 的底层实现

JDK1.8 之前

JDK1.8 之前 HashMap 底层是 数组和链表 结合在一起使用也就是 链表散列。HashMap 通过 key 的 hashcode 经过扰动函数处理过后得到 hash 值,然后通过 (n - 1) & hash 判断当前元素存放的位置(这里的 n 指的是数组的长度),如果当前位置存在元素的话,就判断该元素与要存入的元素的 hash 值以及 key 是否相同,如果相同的话,直接覆盖,不相同就通过拉链法解决冲突。

HashMap 中的扰动函数(hash 方法)是用来优化哈希值的分布。通过对原始的 hashCode() 进行额外处理,扰动函数可以减小由于糟糕的 hashCode() 实现导致的碰撞,从而提高数据的分布均匀性。

JDK 1.8 HashMap 的 hash 方法源码:

JDK 1.8 的 hash 方法 相比于 JDK 1.7 hash 方法更加简化,但是原理不变。

    static final int hash(Object key) {int h;// key.hashCode():返回散列值也就是hashcode// ^:按位异或// >>>:无符号右移,忽略符号位,空位都以0补齐return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);}

对比一下 JDK1.7 的 HashMap 的 hash 方法源码.

static int hash(int h) {// This function ensures that hashCodes that differ only by// constant multiples at each bit position have a bounded// number of collisions (approximately 8 at default load factor).h ^= (h >>> 20) ^ (h >>> 12);return h ^ (h >>> 7) ^ (h >>> 4);
}

相比于 JDK1.8 的 hash 方法 ,JDK 1.7 的 hash 方法的性能会稍差一点点,因为毕竟扰动了 4 次。

所谓 “拉链法” 就是:将链表和数组相结合。也就是说创建一个链表数组,数组中每一格就是一个链表。若遇到哈希冲突,则将冲突的值加到链表中即可。

JDK1.8 之后

相比于之前的版本, JDK1.8 之后在解决哈希冲突时有了较大的变化,当链表长度大于阈值(默认为 8)(将链表转换成红黑树前会判断,如果当前数组的长度小于 64,那么会选择先进行数组扩容,而不是转换为红黑树)时,将链表转化为红黑树,以减少搜索时间。

TreeMap、TreeSet 以及 JDK1.8 之后的 HashMap 底层都用到了红黑树。红黑树就是为了解决二叉查找树的缺陷,因为二叉查找树在某些情况下会退化成一个线性结构。

我们来结合源码分析一下 HashMap 链表到红黑树的转换。

1、 putVal 方法中执行链表转红黑树的判断逻辑。

链表的长度大于 8 的时候,就执行 treeifyBin (转换红黑树)的逻辑。

// 遍历链表
for (int binCount = 0; ; ++binCount) {// 遍历到链表最后一个节点if ((e = p.next) == null) {p.next = newNode(hash, key, value, null);// 如果链表元素个数大于TREEIFY_THRESHOLD(8)if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st// 红黑树转换(并不会直接转换成红黑树)treeifyBin(tab, hash);break;}if (e.hash == hash &&((k = e.key) == key || (key != null && key.equals(k))))break;p = e;
}

 2、treeifyBin 方法中判断是否真的转换为红黑树。

final void treeifyBin(Node<K,V>[] tab, int hash) {int n, index; Node<K,V> e;// 判断当前数组的长度是否小于 64if (tab == null || (n = tab.length) < MIN_TREEIFY_CAPACITY)// 如果当前数组的长度小于 64,那么会选择先进行数组扩容resize();else if ((e = tab[index = (n - 1) & hash]) != null) {// 否则才将列表转换为红黑树TreeNode<K,V> hd = null, tl = null;do {TreeNode<K,V> p = replacementTreeNode(e, null);if (tl == null)hd = p;else {p.prev = tl;tl.next = p;}tl = p;} while ((e = e.next) != null);if ((tab[index] = hd) != null)hd.treeify(tab);}
}

将链表转换成红黑树前会判断,如果当前数组的长度小于 64,那么会选择先进行数组扩容,而不是转换为红黑树。

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

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

相关文章

二十二、MySQL 8.0 主从复制原理分析与实战

文章目录 一、复制&#xff08;Replication&#xff09;1、什么是复制2、复制的方式3、复制的数据同步类型3.1、异步复制3.2、半同步复制3.3、设计理念&#xff1a;复制状态机——几乎所有的分布式存储都是这么复制数据的 4、基于binlog位点同步的主从复制原理4.1、异步复制示例…

测试管理|如何做好质量管理、提高研发的代码质量?

以下为作者观点&#xff1a; 起因是领导一直在提的一个观点&#xff1a;测试不能只测试系统&#xff0c;重点要放到质量管理上&#xff0c;要管理、监督研发的开发质量。 公司是乙方&#xff0c;接项目过日子&#xff0c;算是外包企业吧。项目时间一般都比较紧张&#xff08;…

QT项目-仿QQ聊天(带宠物系统)

目录 一&#xff0c;项目介绍 二&#xff0c;开发环境 三&#xff0c;涉及技术 四&#xff0c;项目效果示例图 1&#xff0c;登录界面 2&#xff0c;主界面 3&#xff0c;聊天界面 4&#xff0c;功能界面 5&#xff0c;宠物界面 一&#xff0c;项目介绍 这是一个基于u…

vue打包项目通过docker部署nginx服务

一、构建前端代码 npm install nmp run build 确认自己的打包路径&#xff0c;默认是dist&#xff0c;这里也可以修改。 二、将打包的项目使用dockerfile构建 dockerfile 将dist文件复制到nginx的指定的路径&#xff0c;前端界面的路径&#xff0c;还需要两个conf文件 FR…

数据分析与效果评估的有效方法与实践探讨

内容概要 在现代社会中&#xff0c;数据分析与效果评估已成为各类项目管理和决策制定中的重要组成部分。首先&#xff0c;数据分析为我们提供了一种系统化的方法&#xff0c;以深入了解所收集数据的内涵与趋势。通过对数据进行整理、分类和分析&#xff0c;我们能够发现潜在的…

【Kettle的安装与使用】使用Kettle实现mysql和hive的数据传输(使用Kettle将mysql数据导入hive、将hive数据导入mysql)

文章目录 一、安装1、解压2、修改字符集3、启动 二、实战1、将hive数据导入mysql2、将mysql数据导入到hive 一、安装 Kettle的安装包在文章结尾 1、解压 在windows中解压到一个非中文路径下 2、修改字符集 修改 spoon.bat 文件 "-Dfile.encodingUTF-8"3、启动…

2024年NSSCTF秋季招新赛-WEB

The Beginning F12看源码&#xff0c;有flag http标头 黑吗喽 题目说要在发售时的0点0分&#xff0c;所以添加标头data Date: Tue, 20 Aug 2024 00:00:00 GMT然后改浏览器头 User-Agent: BlackMonkey曲奇就是Cookie cookieBlackMonkey这个一般就是Referer Referer:wukon…

【Python单元测试】pytest框架单元测试 配置 命令行操作 测试报告 覆盖率

单元测试&#xff08;unit test&#xff09;&#xff0c;简称UT。本文将介绍在Python项目中&#xff0c;pytest测试框架的安装&#xff0c;配置&#xff0c;执行&#xff0c;测试报告与覆盖率 pytest简介 pytest是一款流行的&#xff0c;简单易上手的单元测试框架&#xff0c;…

python之数据结构与算法(数据结构篇)-- 集合

一、集合的概念 所谓的编程中的”集合“&#xff0c;其实和高中数学中集合是一样的的。比如&#xff1a;羊村和狼堡分别看作两个集合&#xff0c;而狼堡中的"灰太狼"、"红太狼"、"小灰灰"则可看作狼堡中的元素&#xff0c;同理&#xff0c;羊村…

C# 企业微信机器人推送消息 windows服务应用程序的使用

C# 企业微信机器人推送消息 先添加一个机器人! 然后查看机器人就可以得到一个 webhook 特别特别要注意&#xff1a;一定要保护好机器人的webhook地址&#xff0c;避免泄漏&#xff01; 然后开始写代码 &#xff0c;只需要httpPost 调用一下这个地址就可以发送消息了。 首先我…

「Mac畅玩鸿蒙与硬件14」鸿蒙UI组件篇4 - Toggle 和 Checkbox 组件

在鸿蒙开发中,Toggle 和 Checkbox 是常用的交互组件,分别用于实现开关切换和多项选择。Toggle 提供多种类型以适应不同场景,而 Checkbox 支持自定义样式及事件回调。本篇将详细介绍这两个组件的基本用法,并通过实战展示它们的组合应用。 关键词 Toggle 组件Checkbox 组件开…

基于SpringBoot+Vue+MySQL的房屋租赁系统

系统展示 系统背景 随着城市化进程的加速和人口流动性的增加&#xff0c;房屋租赁市场逐渐成为城市生活的重要组成部分。然而&#xff0c;传统的房屋租赁方式存在诸多问题&#xff0c;如信息不对称、交易成本高、租赁关系不稳定等&#xff0c;这些问题严重影响了租赁市场的健康…

【MyBatis源码】SqlSession实例创建过程

在MyBatis中&#xff0c;openSession()方法是开启数据库会话的入口&#xff0c;主要作用是生成SqlSession对象。我们从SqlSessionFactory接口入手&#xff0c;其实现类DefaultSqlSessionFactory的openSession()方法用于创建SqlSession实例. SqlSessionFactory接口方法 public…

MoveIt 控制自己的真实机械臂【2】——编写 action server 端代码

完成了 MoveIt 这边 action client 的基本配置&#xff0c;MoveIt 理论上可以将规划好的 trajectory 以 action 的形式发布出来了&#xff0c;浅浅尝试一下&#xff0c;在 terminal 中运行 roslaunch xmate7_moveit_config_new demo.launch 报错提示他在等待 xmate_arm_control…

6977 树的统计

经验值&#xff1a;3200 时间限制&#xff1a;1000毫秒 内存限制&#xff1a;512MB 题目描述 Description 一树上有 nn 个节点&#xff0c;编号分别为 11 到 nn&#xff0c;每个节点都有一个权值 ww。我们将以下面的形式来要求你对这棵树完成一些操作&#xff1a; CHANGE …

SQL之排名RANK()、ROW_NUMBER()、DENSE_RANK() 和 NTILE() 的区别(SQL 和 Hive SQL 都支持)

现有一张student 表,表中包含id、uname、age、score 四个字段,如下所示: 该表的数据如下所示: 一、ROW_NUMBER() 1、概念 ROW_NUMBER() 为结果集中的每一行分配一个唯一的连续整数,编号从 1 开始。‌ 该函数按照指定的顺序进行排序,即使存在相同的值,每一行也会获得…

机器人转人工时,开启实时质检(mod_cti基于FreeSWITCH)

文章目录 前言联系我们实现步骤1. 修改拨号方案2. 启用拨号方案 前言 在客户与机器人对话中&#xff0c;是不能开启质检功能的。因为机器人识别会与质检识别产生冲突。如果用户想通过机器人转接到人工时&#xff0c;开启质检功能&#xff0c;记录客户与人工之间的对话。应该如…

结合Intel RealSense深度相机和OpenCV来实现语义SLAM系统

结合Intel RealSense深度相机和OpenCV来实现语义SLAM系统是一个非常强大的组合。以下是一个详细的步骤指南&#xff0c;帮助你构建这样一个系统。 硬件准备 Intel RealSense深度相机&#xff1a;例如D415、D435或L515。计算平台&#xff1a;一台具有足够计算能力的计算机&…

【JVM 深入了解】JVM 到底包含什么?

&#x1f449;博主介绍&#xff1a; 博主从事应用安全和大数据领域&#xff0c;有8年研发经验&#xff0c;5年面试官经验&#xff0c;Java技术专家&#xff0c;WEB架构师&#xff0c;阿里云专家博主&#xff0c;华为云云享专家&#xff0c;51CTO 专家博主 ⛪️ 个人社区&#x…

炫酷的登录框!(附源码)

大家想看什么前端效果请留言 预览效果 源码 <!DOCTYPE html> <html lang"zh"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>登录页…