1. HashMap 如何实现?
  2. put 做了什么?
  3. get 做了什么?
  4. 初始化容量,满载率,扩展?
  5. hash?
  6. 类似的结构及相似处,不同点?

load factor 满载率

capacity 容量

threshold 临界值

import java.util.Map;public class Test {public static void main(String[] args) {Map<Key, String> map = new HashMap<Key, String>();map.put(new Key("A"), "1");map.put(new Key("B"), "2");map.put(new Key("C"), "3");System.out.println(map);}
}class Key {private String name;Key(String name) {this.name = name;}@Overridepublic int hashCode() {return 1;}@Overridepublic String toString() {return "Key [name=" + name + "]";}
}

import java.util.Map;public class Test {public static void main(String[] args) {Map<Key, Integer> map = new HashMap<Key, Integer>();for (int i = 0; i < 11; i++) {map.put(new Key(System.nanoTime()), i);}System.out.println(map);}
}class Key {private long name;Key(long name) {this.name = name;}@Overridepublic int hashCode() {return 1;}@Overridepublic String toString() {return "Key [name=" + name + "]";}
}

    static final int TREEIFY_THRESHOLD = 8;static final int UNTREEIFY_THRESHOLD = 6;static final int MIN_TREEIFY_CAPACITY = 64;

控制treeify的临界值是8 ,当bin中链大于8时,则尝试treeify

  • 1)如果此时表容量不足64,则会扩表。因此添加第9个元素时,由16->32 ,添加第10个元素时,由32->64
  • 2)添加第11个元素时,此时转为了TreeNode

==============================================

put

    final V putVal(int hash, K key, V value, boolean onlyIfAbsent, boolean evict) {Node<K, V>[] tab;Node<K, V> p;int n, i;// 1 table 为空时重置大小if ((tab = table) == null || (n = tab.length) == 0)n = (tab = resize()).length;// 2  落到空bin 直接添加节点if ((p = tab[i = (n - 1) & hash]) == null)tab[i] = newNode(hash, key, value, null);// 3  落到非空bin ,判断 a , b ,c,else {Node<K, V> e;K k;// a) header与入参key相同,替换旧值if (p.hash == hash && ((k = p.key) == key || (key != null && key.equals(k))))e = p;// b) header是红黑树去添加树节点else if (p instanceof TreeNode)e = ((TreeNode<K, V>) p).putTreeVal(this, tab, hash, key, value);// c) header是链else {// 遍历链,逐项检查 ,判断 I ,IIfor (int binCount = 0;; ++binCount) {// I) 末尾追加节点并检查是否需要转为红黑树if ((e = p.next) == null) {p.next = newNode(hash, key, value, null);if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
                            treeifyBin(tab, hash);break;}// II) key相同则替换旧值 返回if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k))))break;p = e;}}if (e != null) { // existing mapping for keyV oldValue = e.value;if (!onlyIfAbsent || oldValue == null)e.value = value;afterNodeAccess(e);return oldValue;}}++modCount;// 表中元素个数大于临界值时,扩展表X2if (++size > threshold)resize();afterNodeInsertion(evict);return null;}

get

    final Node<K, V> getNode(int hash, Object key) {Node<K, V>[] tab;Node<K, V> first, e;int n;K k;// table 存在,header节点存在if ((tab = table) != null && (n = tab.length) > 0 && (first = tab[(n - 1) & hash]) != null) {// 与 header 节点key相同,返回header 节点if (first.hash == hash && ((k = first.key) == key || (key != null && key.equals(k))))return first;// 如果存在header的子节点if ((e = first.next) != null) {// 如果 header 是红黑树去取树节点if (first instanceof TreeNode)return ((TreeNode<K, V>) first).getTreeNode(hash, key);// 如果 header 是链do {// 遍历节点,找到相同key返回if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k))))return e;} while ((e = e.next) != null);}}// 未查到相同keyreturn null;}

treeify

    final void treeifyBin(Node<K, V>[] tab, int hash) {int n, index;Node<K, V> e;// 如果table达不到最小treeify 容量(64)则扩容X2if (tab == null || (n = tab.length) < MIN_TREEIFY_CAPACITY)resize();// header 节点存在时else if ((e = tab[index = (n - 1) & hash]) != null) {TreeNode<K, V> hd = null, tl = null;// 遍历链将 Node -> TreeNodedo {TreeNode<K, V> p = replacementTreeNode(e, null);if (tl == null)hd = p;else {p.prev = tl;tl.next = p;}tl = p;} while ((e = e.next) != null);if ((tab[index] = hd) != null)// 绘制红黑树
                hd.treeify(tab);}}

resize

    /*** Initializes or doubles table size.  If null, allocates in* accord with initial capacity target held in field threshold.* Otherwise, because we are using power-of-two expansion, the* elements from each bin must either stay at same index, or move* with a power of two offset in the new table.** @return the table*/final Node<K, V>[] resize() {...return newTab;}

hash

    /*** Computes key.hashCode() and spreads (XORs) higher bits of hash* to lower.  Because the table uses power-of-two masking, sets of* hashes that vary only in bits above the current mask will* always collide. (Among known examples are sets of Float keys* holding consecutive whole numbers in small tables.)  So we* apply a transform that spreads the impact of higher bits* downward. There is a tradeoff between speed, utility, and* quality of bit-spreading. Because many common sets of hashes* are already reasonably distributed (so don't benefit from* spreading), and because we use trees to handle large sets of* collisions in bins, we just XOR some shifted bits in the* cheapest possible way to reduce systematic lossage, as well as* to incorporate impact of the highest bits that would otherwise* never be used in index calculations because of table bounds.*/static final int hash(Object key) {int h;return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);}

关于编写方法时使用的缩略词猜想

  • mc = modCount
  • tab = table
  • bin = table[i]
  • tl = tree left
  • hd = header
  • p = present
  • i = index
  • prev = previous
  • next = next
  • k = key
  • val = value
  • v = value
  • n = length
  • e = entry
  • simple -> simplify
  • tree -> treeify
  • do -> undo
  • untreeify -> untreeify

转载于:https://www.cnblogs.com/zno2/p/7500015.html

java.util.HashMap相关推荐

  1. 解决Apache CXF 不支持传递java.sql.Timestamp和java.util.HashMap类型问题

    在项目中使用Apache开源的Services Framework CXF来发布WebService,CXF能够很简洁与Spring Framework 集成在一起,在发布WebService的过程中 ...

  2. 关于spring mybateis 定义resultType=java.util.HashMap

    关于spring mybateis 定义resultType="java.util.HashMap" List<HashMap<String, Object>&g ...

  3. Android之奔溃提示com.google.gson.internal.LinkedTreeMap cannot be cast to java.util.HashMap

    1 问题 Android端获取服务端的数据然后我直接把数据转hashMap提示错误如下, com.google.gson.internal.LinkedTreeMap cannot be cast t ...

  4. java map clone_Java中HashMap的clone()方法: java.util.HashMap.clone() - Break易站

    Java中的HashMap java.util.HashMap.clone()方法用于返回所提到的哈希映射HashMap的浅表副本.它只是创建了map的副本. HashMap.clone句法: Has ...

  5. ibatis中配置parameterClass=java.util.HashMap的用法

    引用:http://blog.163.com/gaoxp126@126/blog/static/28094398200743185151903/ 我们可以使用HashMap作为parameterCla ...

  6. Java中如何给map数组制空,java.util.HashMap可以存储null键和null值。( )

    java.util.HashMap可以存储null键和null值.( ) 答:对 2008年网络新词新语大多与国家的社会生活息息相关,体现出网民高涨的参政议政热情和明显的舆论监督意识. 答:对 冯·诺 ...

  7. 当Mybits中resultType=“java.util.HashMap“,结果会怎样

    当使用Mybits框架,有时需要自行在mapper.xml文件中写SQL语句,例如: <select id="test" resultType="java.util ...

  8. JDK源码笔记-java.util.HashMap

    2019独角兽企业重金招聘Python工程师标准>>> HashMap 的存储实现 当程序试图将多个 key-value 放入 HashMap 中时,以如下代码片段为例: Java代 ...

  9. myibatis 报错 Could not find result map java.util.HashMap

    mybatis异常:Could not find result map Java.util.Map 问题分析及解决 错误写法   <select id="queryXXXCount&q ...

最新文章

  1. 二次元少女生成器、会开车的神经网络...2019年最好的17个机器学习项目!
  2. 用CURD来拯救前端的一切的一切
  3. 最新xampp下安装mod_security,mod_evasive,mod-cband笔记
  4. 工作165:混入调用的时候
  5. cad应用程序的组件中发生了未经处理的异常_什么是CAD/CAM?
  6. C#LeetCode刷题之#110-平衡二叉树(Balanced Binary Tree)
  7. webpack loader使用
  8. 数组实例的find() 和 findIndex()方法
  9. 大数据发展的7个趋势 -- 阿里技术专家权威解读
  10. 尚硅谷韩顺平Linux教程学习笔记
  11. 如何制作PE系统盘?
  12. Envoy 架构、术语与基本配置解析
  13. Cesium PolygonGeometry的移动、拉伸、旋转——拉伸
  14. 卫生洁具安装工艺标准
  15. python列表换行输出_Python从列表转换为字符串时处理换行符
  16. iOS 使用系统相册获取选取图片的名称
  17. 用labview设计jk触发器_编写数字电路JK触发器仿真程序
  18. 视频格式转换器哪个好?用什么软件转换格式
  19. ICC II 3 从create_ndm开始design setup
  20. 台式计算机dvd光驱在哪里,用台式电脑怎么放DVD

热门文章

  1. Python入门--字符串的查询操作,find,rfind,index,rindex
  2. linux+多路复用socket,socket的select_多路复用
  3. python打印对象地址_Python打印对象的全部属性
  4. [leetcode]5355. T 秒后青蛙的位置
  5. poj 3268 bzoj 1631: [Usaco2007 Feb]Cow Party(最短路)
  6. ubuntu14.04安装tensorflow-gpu
  7. C++的STL标准库学习(deque)双向队列
  8. 李开复:多次失败后,我总结出最优秀创业者的4个特点
  9. 前端动画大全:css的transition、css3的animation、Jquery的animate、js的setInterval
  10. quartus仿真22:优先编码器74148的级联(详细)