HashMap
基于哈希表的 Map 接口的实现。
此实现提供所有可选的映射操作,并允许使用 null 值和 null 键。
(除了不同步和允许使用 null 之外,HashMap 类与 Hashtable 大致相同。)
此类不保证映射的顺序,特别是它不保证该顺序恒久不变。
(from JDK DOC)

缺省的 Map大小是 16. (这里要求必须是 2 的幂数,为什么一定是 2的幂数(16,32,64,128...下边有解释).
 static final int DEFAULT_INITIAL_CAPACITY = 16;

缺省的比例因子是 0.75
 static final float DEFAULT_LOAD_FACTOR = 0.75f;

长度必须总是 2 的 幂数。
 保存 K,V 对象的数组
 transient Entry[] table;

/**
      * The next size value at which to resize (capacity * load factor).
      * @serial
      */
 重设 Entry[] table 的阀值( = capacity * load factor) 
 int threshold;

当前比例因子
 final float loadFactor;

记录修改次数  
 transient volatile int modCount;

/**
     * Constructs an empty <tt>HashMap</tt> with the specified initial
     * capacity and load factor.
     *
     * @param  initialCapacity The initial capacity.
     * @param  loadFactor      The load factor.
     * @throws IllegalArgumentException if the initial capacity is negative
     *         or the load factor is nonpositive.
     */
    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);

// Find a power of 2 >= initialCapacity
        int capacity = 1;
        while (capacity < initialCapacity)
            capacity <<= 1;
   
        this.loadFactor = loadFactor;
        threshold = (int)(capacity * loadFactor); loadFactor 默认是 0.75. 所以 threshold 默认是 12
        table = new Entry[capacity]; 按照给定的大小初化 Entry 数组。(默认情况下是  16 )
        init();
    }
 
  
 
    看了下边这几行代码就能看出来 HashMap是怎么支持 null 做为 Key了。
    static final Object NULL_KEY = new Object();
    static <T> T maskNull(T key) {
        return key == null ? (T)NULL_KEY : key;
    }
    static <T> T unmaskNull(T key) {
        return (key == NULL_KEY ? null : key);
    }

HashMap 对key 值的  hash 算法。
    Object 类使用的 对象的 内部地址 提供 hashCode.
    String 使用一个算法提供hashCode。(算法:s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1])
    当然这样一种算法是不能完全保证 得到的hashCode是唯一的。
   
    String s1 = "结算";
    String s2 = "罚款";
    两个对象的hashcode是相同的(1038116);
    经过hash之后是-423929781.
   
    这个函数的算法我就看不大懂了。还有高人指教了。
 
    static int hash(Object x) {
        int h = x.hashCode();
        h += ~(h << 9);
        h ^=  (h >>> 14);
        h +=  (h << 4);
        h ^=  (h >>> 10);
        return h;
    }
   
    根据hashCode值 值和 当前 Entry数组的长度计算 该数据应该在数组中的索引值
    因为这里的算法 所以 capacity 大小必须为 2 的幂数。
    举例,默认值是 16 , 其减1是 15, 二进制是 00001111 .
    h 是一个特殊的 hash值。 与  0x0F进行 & 操作当然结果应该在 0x0F以内了。
    但这里必须保证 length -1 全为 1. 否则话某些位可能永远是 0,那么Entry数组
    的一个范围可能永远也不会被用到。
   
    这里没使用取余计算应该出于效率考虑的吧。
    static int indexFor(int h, int length) {
        return h & (length-1);
    }
   
   
    public V get(Object key) {
        Object k = maskNull(key);    //检查是否是null Key
        int hash = hash(k);          //计算hash
        int i = indexFor(hash, table.length); //计算索引
        Entry<K,V> e = table[i];              //取得Entry对象
        while (true) {                        //循环查找链上 对象
            if (e == null)

转载于:https://www.cnblogs.com/hcmsxy/archive/2008/07/18/2164062.html

JDK 1.5 HashMap 源代码读解相关推荐

  1. HashMap源代码详解

    HashMap类声明 HashMap类声明如下: public class HashMap<K,V> extends AbstractMap<K,V> implements M ...

  2. 【Java基础】HashMap原理详解

    [Java基础]HashMap原理详解 HashMap的实现 1. 数组 2.线性链表 3.红黑树 3.1概述 3.2性质 4.HashMap扩容死锁 5. BATJ一线大厂技术栈 HashMap的实 ...

  3. HashMap原理详解(基于jdk1.8)

    HashMap原理详解(基于jdk1.8) HashMap原理详解,有兴趣的同学可以看下.有错误的地方也希望大佬们能指点下. HashMap的内部存储是一个数组(bucket),数组的元素Node实现 ...

  4. 查看源代码Source not found及在eclipse中配置jdk的src.zip源代码

    查看源代码Source not found及在eclipse中配置jdk的src.zip源代码 https://blog.csdn.net/tuke_tuke/article/details/5154 ...

  5. Spring框架学习day_02:组件扫描 / 注解内部读解 / 组件扫描中配置作用域和生命周期 / 解耦 / 自动装配(两种方式) / 读取文件

    1. 组件扫描 首先,必须让Spring扫描组件所在的包,并且,组件类的声明之前必须添加@Component注解! 其实,除了@Component注解以外,还可以使用以下注解实现同样的效果: @Con ...

  6. Atitit.jdk java8的语法特性详解 attilax 总结

    Atitit.jdk java8的语法特性详解 attilax 总结 1.1. 类型推断这个特别有趣的.鲜为人知的特性1 2. Lambda1 2.1. 内部迭代意味着改由Java类库来进行迭代,而不 ...

  7. kbengine 源代码读

    第一时间更新地址:kbengine bbs 以下摘自百度百科: """ KBEngine是一款开源的游戏服务端引擎,使用简单的约定协议就能够使客户端与服务端进行交互, 使 ...

  8. 《四书五经》之大学全文、注释及读解 好东西啊

    http://www.douban.com/group/topic/2058726/[原文]    大学之道(1),在明明德(2),在亲民(3),在止于至善. 知止(4)而后有定:定而后能静:静而后能 ...

  9. emule中节点加入Kad网络过程(源代码详解)【对原文部分改进】

    from: http://blog.csdn.net/chenbuaa/article/details/2301656 emule中节点加入Kad网络过程(源代码详解) 程序启动: EmuleDlg. ...

  10. java JDK安装与环境配置详解(超超超级详细)

    点击以下链接获取详细图文教程! java JDK安装与环境配置详解 https://v.xiumi.us/board/v5/3QTAV/112689421

最新文章

  1. 2020年一季度中小微企业收入平均下降69.5%
  2. jenkins~管道Pipeline里使用公用类库
  3. 科大星云诗社动态20210808
  4. 怎样对流媒体进行压力测试_暖气片怎样安装效果好?暖气片正确的安装,采暖效果更好!...
  5. java多个mapreduce_一个简单的MapReduce示例(多个MapReduce任务处理)
  6. 基于模板的文字识别结果结构化处理技术
  7. mysql timestamp类型比较_MySQL timestamp 类型比较的测试
  8. 光电雷达智能跟踪平台
  9. 第二周函数-的基本格式:
  10. 【2019杭电多校第六场1011=HDU6644】11 Dimensions(dp+思维)
  11. js,如何把省份简称转换成省份全称
  12. java抓包WIFI包_教你手机应用如何通过wifi上网抓包
  13. 介绍几款知名的工作流系统软件
  14. 记录一个非常好用的模拟器:夜神模拟器
  15. 安兔兔html5测试跑分榜,2021年最新安兔兔手机性能跑分排行榜
  16. Bitmap、CBitmap、HBITMAP以及BITMAP的相互转换
  17. 人工智能 | ShowMeAI资讯日报 #2022.06.13
  18. [设计模式] 调停者模式(Mediator Pattern)
  19. 面试题19/leetcode10:正则表达式匹配 C++
  20. ERC721: Non-fungible Token Standard

热门文章

  1. ERROR 1045 (28000): Access denied for user 'admin'@'localhost' (using password: YES)
  2. Log_Analysis_using_OSSEC.md
  3. HDU 4859 海岸线(最大流最小割)
  4. 我怎么感觉js快无敌了~
  5. 使用finalize/dispose 模式提高GC性能(翻译)
  6. jquery ajax get 数组参数
  7. 使用多线程提高Rest服务性能
  8. Solr进阶之Solr综合文本相似度的多因素权重排序实现
  9. NFS, web,负载均衡,Nginx yum 源码安装
  10. ELK——Logstash 2.2 mutate 插件【翻译+实践】