当前位置: 首页 > news >正文

Java高频面试之集合-14

hello啊,各位观众姥爷们!!!本baby今天来报道了!哈哈哈哈哈嗝🐶

面试官:为什么 HashMap 的容量是 2 的倍数呢?


HashMap的容量被设计为2的幂次,主要基于以下原因:

  1. 高效的索引计算

    • 位运算替代取模:当容量为2的幂次时,计算元素在数组中的索引可以通过位运算 hash & (capacity - 1) 实现,效率远高于取模运算 hash % capacity。例如:
      // 当 capacity = 16 (2^4) 时:
      int index = hash & (16 - 1); // 等价于 hash % 16,但更快
      
    • 硬件优化:位运算在底层硬件中执行更快,仅需几个时钟周期,而取模运算需要更多指令。
  2. 均匀的哈希分布

    • 哈希函数优化:HashMap对键的哈希值进行二次处理(如异或高位与低位),确保低位分布更均匀:
      static final int hash(Object key) {
          int h;
          return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
      }
      
    • 减少冲突:当容量为2的幂次时,哈希值的高位信息通过按位与操作参与索引计算,避免仅依赖低位导致冲突。
  3. 扩容的便捷性

    • 容量翻倍:扩容时容量直接翻倍(如16→32),新索引可通过位运算快速确定:
      // 旧容量为16时,扩容后为32:
      if ((e.hash & oldCap) == 0) {
          // 新索引 = 原索引
      } else {
          // 新索引 = 原索引 + 原容量
      }
      
    • 减少重新哈希开销:无需重新计算所有元素的索引,仅需判断高位是否为1。
  4. 用户输入的自动修正

    • 容量对齐:若用户指定初始容量非2的幂次,HashMap会通过 tableSizeFor() 方法调整为最近的2的幂次:
      static final int tableSizeFor(int cap) {
          int n = cap - 1;
          n |= n >>> 1;
          n |= n >>> 2;
          n |= n >>> 4;
          n |= n >>> 8;
          n |= n >>> 16;
          return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
      }
      

总结

设计选择优势
2的幂次容量位运算高效计算索引,提升性能。
哈希函数优化高位参与索引计算,减少哈希冲突。
扩容机制翻倍扩容配合位运算,快速重新分配元素。
自动容量修正确保用户输入的容量符合2的幂次,保持设计一致性。

示例

  • 容量16(2⁴):二进制为1000016 - 1 = 151111),索引计算为hash & 1111,覆盖哈希值的低4位。
  • 扩容到32:原索引为hash & 1111,扩容后索引为hash & 11111,仅需判断第5位是否为1即可确定新位置。

通过以上机制,HashMap在性能、冲突处理及扩展性上达到平衡,成为高效的键值存储结构。

在这里插入图片描述

相关文章:

  • 【WEB APIs】正则表达式
  • AI小白的第六天:必要的数学知识(一)
  • 解决 Nginx 访问 /root/下 403 Forbidden 问题
  • 线程大乱斗:从入门到精通,解锁Java并发编程的终极秘籍
  • MTK Android12 应用在最顶端时,禁止拉起其他某个应用(一)
  • docker环境下安装flink
  • vector(沉淀)
  • 使用Azure CDN进行子域名接管
  • 解锁 DeepSeek 安全接入、稳定运行新路径
  • vulhub-joker攻略
  • VulnHub-Billu_b0x通关攻略
  • 【C++】多态
  • CCF-CSP认证 202206-1归一化处理
  • Compose 的产生和原理
  • MySQL超详细介绍(近2万字)
  • 穆迪暖色调人像静物摄影后期Lr调色教程,手机滤镜PS+Lightroom预设下载!
  • 生成PDF文件:从html2canvas和jsPdf渲染到Puppeteer矢量图
  • Android Handler 通过线程安全的 MessageQueue 和底层唤醒机制实现跨线程通信
  • 【嵌入式学习】如何利用gitee管理记录学习内容
  • 多线程—进程与线程
  • 第1现场 | 50多年来首次!印度举行大规模民防演习
  • 罗氏制药全新生物制药生产基地投资项目在沪启动:预计投资20.4亿元,2031年投产
  • 轿车追尾半挂车致3死1伤,事故调查报告:司机过分依赖巡航系统
  • 短剧剧组在贵州拍戏突遇极端天气,演员背部、手臂被冰雹砸伤
  • 金沙记忆|元谋龙街渡:是起点也是终点
  • 独家专访|白先勇:我的家乡不是哪个地点,是中国传统文化