HashMap

JDK 版本: 1.8.0_45

常量

  • DEFAULT_INITIAL_CAPACITY = 16; 默认容器大小 2的整数幂
  • MAXIMUM_CAPACITY = 1<<30; 最大容器大小 2的整数幂
  • DEFAULT_LOAD_FACTOR = 0.75f; 负载因子, 当容器中的数据占用容器达到 75% 时, 进行扩容
  • TREEIFY_THRESHOLD = 8; 当冲突的数据量到达这个值时, 转成二叉树存储
  • UNTREEIFY_THRESHOLD = 6; resize 之后, 如果冲突的项小于这个值, 则转成链表形式
  • MIN_TREEIFY_CAPACITY = 64; 如果容器大小小于这个值, 则不会使用二叉树, 而是先扩容,

主要成员变量

  • table: 存放键值对的数组, 大小是2的整数次幂, 如果数据量超过了负载因子, 会自动扩容
  • entrySet: 用于 keySet() 和 values()
  • size: 键值对的数量
  • modCount: 操作次数(增加/删除键值对), 处理集合全部元素时, 如果有其他线程操作集合则报错
  • threshold: 下一次扩容的键值对数量, (即当前容量*负载因子)

主要方法

  1. put(int hash, K key, V value, boolean onlyIfAbsent, boolean evict)

    put(...) 方法最终都调用这个方法, 操作如下:

    1. 获取容器(table)大小, 如果容器未初始化, 则调用(resize())初始化
    2. 如果table中(hash&(n-1))值所在的桶是空, 则table[hash&(n-1)]直接指向当前对象(结束)
    3. 否则, 如果找到 key 相同的键值对, 则直接将键值对的值设置为当前值, 返回旧值
    4. 如果当前对象是一个 TreeNode, 则直接插入到这个二叉树中, 如果值已存在, 替换并返回旧值, 否则插入到尾部返回 null
    5. 如果当前是链表, 则遍历, 有相同的key就替换, 没有就插入到尾部, 如果链表长度大于等于 TREEIFY_THRESHOLD 则转成二叉树(TreeNode)
  2. removeNode(int hash, Object key, Object value, boolean matchValue, boolean movable)

    1. 如果table 为空, 或者table[hash&(n-1)] 为空, 直接返回 null (结束)
    2. 查找 key 值相同的对象(从链表或者TreeNode中查找)
    3. 查找到, 则再匹配 value, 如果有需要的话, 匹配成功则删除这个键值对

数据结构

Paste_Image.png

TreeNode 是一个红黑树, 查找删除的复杂度都是 Log(n), 上图的树画的不对

总结

  1. HashMap 全部方法都没有进行同步处理的, 因此尽量不要在多线程中使用
  2. Java8 的 HashMap 跟以前的版本不一样了, 代码有了更多的优化
    1. 现在的版本使用二叉树(TreeNode)解决 key 冲突时的查找效率问题
    2. 现在的要求容器大小必须是2的幂次, 计算键值对所在的桶因此页不需要使用取余符号了(位运算效率高)
    3. 以前的版本为了解决某个 key 冲突比较多, 在 rehash() 时会将容器扩大1倍+1, 这样原来冲突的key现在极有可能不冲突了. 而现在的版本, 当容器扩大时, 原来冲突的现在很有可能继续冲突, 使用二叉树优化, 可以达到更好的效果
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 前言 这次我和大家一起学习HashMap,HashMap我们在工作中经常会使用,而且面试中也很频繁会问到,因为它里...
    liangzzz阅读 12,426评论 7 102
  • 前文:HashMap是Java程序员最常用的映射(键值对)处理数据的容器。随着JDK版本的更新,1.8相较于1.7...
    是一动不动的friend阅读 5,037评论 0 1
  • 今天晚上,我和爸爸在家里玩追人游戏。爸爸背着弟弟跑,我来追。玩完之后爸爸说:“他已经被我玩的上气不接下气了。哈...
    欧阳至俊阅读 1,252评论 0 0
  • 如果人生百年,值得记住的年份可能不多,每年经历的事情放在百年的长河里面可能都显得微不足道。可是2015年,在我人生...
    小苤阅读 1,297评论 0 1
  • 我明明跟你说,这就是小事一桩,你偏惊慌的要死,以为遇上多大的拦路虎,其实就只是个戴面具的蚂蚁而已。要照你这样下去,...
    希文啊阅读 3,218评论 0 3

友情链接更多精彩内容