AI工具人
提示词工程师

Java HashMap源码浅析

  之前虽然很频繁使用java的hashmap,但一直都是纯用,至于里面怎么实现的,一直都是糊里糊涂的。今年4月份跳槽找工作,大概看了一下HashMap的源码,在面试过程中也被多位面试官问到HashMap的相关问题,有些问题也没回答出来。本来几个月前就想着写一篇相关源码解析的博客(主要是加深自己的理解),一直拖到现在,接下来就跟我一起看下HashMap的实现(基于jdk8)。

  
  HashMap实现了Map,Cloneable,Serializable三个接口,Map定义了必要方法,Cloneable意味着HashMap是可被clone的,Serializable以为这HashMap可以被序列化。但是AbstractMap是什么鬼?打开AbstractMap的源码就会发现注释第一句就告诉你,AbstractMap给Map提供了一个骨架,事实上它实现了Map的几乎所有的方法,除了entrySet()。AbstractMap既然实现了Map接口,那为什么HashMap还要实现Map接口? 好吧关于这个问题,有人说是个作者的一个失误,见StackOverflow,我觉得这个说法站不住脚啊,如果是个失误,为啥到jdk10还没被修复,跳过这个问题。
  打开HashMap的源码,跳过一堆注释,最先看到的是几个常量,这几个常量是缺省时的默认值,非常重要,它们决定这HashMap在使用过程中内部的发生的一些行为,我们挨个看一下。

long serialVersionUID = 362498820763181265L;   //用来在序列化时校验用的  
int DEFAULT_INITIAL_CAPACITY = 1 << 4;   //缺省时HashMap的初始容量 16
int MAXIMUM_CAPACITY = 1 << 30;  //最大容量  
float DEFAULT_LOAD_FACTOR = 0.75f;  //缺省时的默认负载因子,当map中的存储量占总容量的75%以上,hashmap就会把自身容量扩张一倍
int TREEIFY_THRESHOLD = 8;  // 触发树化阀值
int MIN_TREEIFY_CAPACITY = 64;  // 真正树化阀值 

  了解一个类,应该最先从其构造函数开始,HashMap可选的构造参数并不多,最核心的就这一个构造方法,如下。

    public HashMap(int initialCapacity, float loadFactor) {
        if (initialCapacity < 0)
            throw new IllegalArgumentException("Illegal initial capacity: " +
                                               initialCapacity);
        if (initialCapacity > MAXIMUM_CAPACITY)
            initialCapacity = MAXIMUM_CAPACITY;
        if (loadFactor <= 0 || Float.isNaN(loadFactor))
            throw new IllegalArgumentException("Illegal load factor: " +
                                               loadFactor);
        this.loadFactor = loadFactor;
        this.threshold = tableSizeFor(initialCapacity);
    }

  这个构造函数做的事很简单,只是初始化了两个值,一个是负载因子,如果用户用自定义切校验通过就会抛弃默认的0.75负载因子。另一个是threshold,loadFactor是个负载因子的比例,threhold才是实际值,HashMap会根据threhold具体值来做resize()。这里我们顺带看下tableSizeFor()的实现。

赞(2) 打赏
未经允许不得转载:XINDOO » Java HashMap源码浅析
描述文字

评论 抢沙发

觉得文章有用就打赏一下文章作者

非常感谢你的打赏,我们将继续给力更多优质内容,让我们一起创建更加美好的网络世界!

支付宝扫一扫

微信扫一扫