HashMap学习笔记

HashMap学习笔记

  1. 初始容量
    在构造HashMap的时候根据预期的entry数量考虑初始容量和负载因子,这样可以尽可能的避免rehash。如果有很多kv要存在HashMap中,创建一个足够大的实例来存储要比让hashmap需要扩容时自动rehash要更加高效。

  2. 负载因子
    load factor = entry.size / hashmap capacity

  3. Comparable
    使用许多相同hashCode的key肯定会降低性能。为了改善冲突,当key是Comparable时,这个类会通过在key之间比较顺序来打破纽带。从java8开始,当hash 冲突的长度超过一定的阈值(8)并且map的容量超过一定的阈值(64),hashMap会把链表变成一个红黑树(一直平衡)。当HashMap实现尝试在树中查找新条目的位置时,首先检查当前值和新值是否是Comparable。如果不是的话,只能通过tieBreakOrder(Object a, Object b)来比较,这个方法会先比较class name,然后使用System.identityHashCode。如果是Comparable的,那么事情就简单了,通过compareTo接口就可以比较了。值得一提的是,根据compareTo方法(该方法返回0),当两个Comparable键结果相等时,将使用相同的tieBreakOrder方法。

  4. resize(初始化table或者对table进行double 扩容)

    1. 如果没有初始化,那么此方法就是初始化table的方法,默认的capacity是16,负载因子是0.75。
    2. 已经初始化,那么要对
  5. rehash过程(参考链接

    • java7 resize过程中每一个元素都要重新通过indexFor(hash)计算位置,然后将元素插入到新数据到链表头部,形成了反序(在并发的情况下有可能形成回环)。
    • java8 采用2倍扩容,扩容后,resize过程中,每一个元素通过与oldCap取&,看看结果是1还是0,如果是0的话,分配新表的原索引位置,如果是1的话,分配到新表的(原索引位置+oldCap)位置,两者都是将元素插入到链表尾(保持了元素相对顺序没有发生变化)。这个原因是在根据hash定位数组索引位置的时候是通过hash&(n-1)来做的,2倍扩容以后hash&(n-1)的结果只有高位会发生变化,只有发生变化的才需要迁移到新的索引位置,可以通过hash&oldCap得到高位的值,通过高位的值是否为1来判断采取的动作
  6. 线程安全
    HashMap是非线程安全的,如果有多个线程并发地对hashmap进行结构性变化,那么就必须额外的同步。通常是由同步持有HashMap实例的对象来完成对hashmap的同步的。如果没有这样的对象存在,这个map应该被Collections.synchronizedMap方法来包装,最好是在创建时完成,来阻止意外的非同步的对hashmap的访问。HashMap的所有视图方法都是Fail-Fast的。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 摘要 HashMap是Java程序员使用频率最高的用于映射(键值对)处理的数据类型。随着JDK(Java Deve...
    周二倩你一生阅读 5,023评论 0 5
  • HashMap 是 Java 面试必考的知识点,面试官从这个小知识点就可以了解我们对 Java 基础的掌握程度。网...
    野狗子嗷嗷嗷阅读 11,669评论 9 107
  • 杨倩,焦点讲师三期,坚持分享492天(2018-5-6) 规则 实践证明,事先的约定比时...
    温心怡然阅读 754评论 0 0
  • 今年我二十,大二 上大学这两年我一直不知道自己到底是在上些什么,我无数次思考这几年我到底在干些什么,干了些什么,甚...
    变变阅读 1,534评论 0 0
  • 15年前踏入大学校门,和舍友们相处不过短短一周的时间,我就深刻地意识到:家乡的教育很落后,最大的落后就是教育资源的...
    12点4元阅读 1,157评论 0 0