HashMap源代码解析
HashMap原理剖析
之前有看过别人的HashMap源代码的分析,今天尝试自己来分析一波,纯属个人愚见。听一些老的程序员说过,当别人跟你说用某样技术到项目中去,而你按照别人的想法实现了的时候,你只能是一个码农,当你自己会想到用一样东西到你的实际开发中的时候,你是一个普通的程序员,当你不仅能想到用某样技术到项目中去,而且深深的熟悉这项技术的底层实现,那就是一个有内功的程序员了。
HashMap,哈希表,基于哈希算法实现的一个java集合。起初使用这个哈希表的时候,感觉非常的不习惯,主要是容易和其他的几种哈希表搞混,就当时的理解来说,哪个哈希表的键不能为空,哪个哈希表的值可以为空等等,觉得这些东西记住了就感觉自己非常的牛逼了。但是随着学习的进一步深入,总会有疑问,哈希表到底是如何实现的?那就按照api的方法来一个一个解释。
构造方法:
1.空参数的构造方法
1 public HashMap() { 2 //初始化加载因子,等于默认的加载因子0.75 3 this.loadFactor = DEFAULT_LOAD_FACTOR; 4 //最大容量为初始化容量乘以加载因子 5 threshold = (int)(DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR); 6 //初始化一个长度为16的entry数组,也就是存放键值对的数组 7 table = new Entry[DEFAULT_INITIAL_CAPACITY]; 8 //调用init方法 9 init(); 10 }
2.初始化容量的构造方法
1 public HashMap(int initialCapacity) { 2 //调用两个参数的构造方法,初始化容量和默认加载因子 3 this(initialCapacity, DEFAULT_LOAD_FACTOR); 4 }
3.初始化容器和初始化加载因子的构造方法
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); int capacity = 1; while (capacity < initialCapacity) capacity <<= 1; this.loadFactor = loadFactor; threshold = (int)(capacity * loadFactor); table = new Entry[capacity]; init(); }
4.Map集合作为参数的构造方法
1 public HashMap(Map<? extends K, ? extends V> m) { 2 //调用初始化加载因子和初始化容量两个参数的构造方法 3 this(Math.max((int) (m.size() / DEFAULT_LOAD_FACTOR) + 1, 4 DEFAULT_INITIAL_CAPACITY), DEFAULT_LOAD_FACTOR); 5 //将参数Map中的key-value对放入新创建的map集合中 6 putAllForCreate(m); 7}
存放键值对的方法:
1 public V put(K key, V value) { 2 //如果key为空,则调用放入null key的方法,占用entry数组的一个位置 3 if (key == null) 4 return putForNullKey(value); 5 //根据key值计算出hash码值 6 int hash = hash(key.hashCode()); 7 //并根据哈希码的值计算出该key-value在entry数组中的存放位置 8 int i = indexFor(hash, table.length); 9 //根据索引直接定位到那个元素并且从那个元素开始遍历 10 for (Entry<K,V> e = table[i]; e != null; e = e.next) { 11 Object k; 12 if (e.hash == hash && ((k = e.key) == key || key.equals(k))) { 13 V oldValue = e.value; 14 e.value = value; 15 e.recordAccess(this); 16 return oldValue; 17 } 18 } 19 20 modCount++;//修改次数加1 21 addEntry(hash, key, value, i);//将key-value对添加进入entry数组 22 return null; 23 }