当前位置: 首页 > 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在性能、冲突处理及扩展性上达到平衡,成为高效的键值存储结构。

在这里插入图片描述

http://www.dtcms.com/a/76443.html

相关文章:

  • 【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管理记录学习内容
  • 多线程—进程与线程
  • 【软考-架构】8.2、开发方法-TPC-MIS-DSS
  • RSI 量化策略实战指南:基于 iTick 报价源的 Python 实现
  • 卷积神经网络 - 卷积层
  • 库的制作与原理 linux第课
  • LORA的AB矩阵是针对Transformer的多头还是MLP
  • 台式机电脑组装---电脑机箱与主板接线
  • 线程池的拒绝策略适用场景思考
  • 网络编程套接字【端口号/TCPUDP/网络字节序/socket编程接口/UDPTCP网络实验】
  • 双曲空间学习记录
  • TypeScript Symbols 深度解析:在 Vue3 中的高级应用实践