浪子归家|HashMap源码分析
相信但凡是Java程序员或者初学者都对HashMap都不陌生 , 而且在代码中大量使用过 , 但是很多人可能只知道HashMap是键值对保存数据 。 如果问到HashMap的实现原理 , 可能大部分人只知道是HashMap是基于数组加链表实现的 。 再深入可能就不太清楚了 。
今天就从源码级别来分析HashMap的实现原理!
打开HashMap源码我们就可以看到一些常量 。
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16 static final int MAXIMUM_CAPACITY = 1 << 30;static final float DEFAULT_LOAD_FACTOR = 0.75f;static final int TREEIFY_THRESHOLD = 8;static final int UNTREEIFY_THRESHOLD = 6;static final int MIN_TREEIFY_CAPACITY = 64;从代码注释也就看到这些常量所代表的含义 ,
DEFAULT_INITIAL_CAPACITY代表的是HashMap数组的初始容量为16;
MAXIMUM_CAPACITY代表HashMap的最大容量 , 但是可以通过构造函数来修改;
DEFAULT_LOAD_FACTOR代表默认加载因子为0.75 , 这个值的作用是在如果HashMap容量使用超过75%的时候触发扩容机制;
TREEIFY_THRESHOLD这个值表示如果链表的长度>=8就由链表转换成红黑树;
UNTREEIFY_THRESHOLD = 6表示如果链表长度 <= 6 , 则会由树重新退化为链表;
MIN_TREEIFY_CAPACITY = 64表示链表转变成树之前 , 还会有一次判断 , 只有数组长度大于 64 才会发生转换 。
然后来看看HashMap的构造函数 , 一共有四个
public HashMap() {this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted}public HashMap(int initialCapacity) {this(initialCapacity, DEFAULT_LOAD_FACTOR);} public HashMap(Map extends K, ? extends V> m) {this.loadFactor = DEFAULT_LOAD_FACTOR;putMapEntries(m, false);}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);}最常用的应用是HashMap()、HashMap(int initialCapacity)和HashMap(int initialCapacity, float loadFactor) , 都很简单易懂 , 无参即采用默认的设置初始化 , HashMap(int initialCapacity)采用指定容量初始化 , HashMap(int initialCapacity, float loadFactor)是指定容量和加载因子的方式初始化 , HashMap(Map extends K, ? extends V> m)这个反正平时我自己是没怎么使用 , 是通过已有的map在构造HashMap,加载因子默认 , 容量取决于map的容量 , 但是并非等于map的容量 , 看完后续就会明白 。
下面再看看经常用的put和get方法
public V put(K key, V value) {return putVal(hash(key), key, value, false, true);}可以看到put实际调用的是putVal方法 , 前面的参数都很简单 , 第四个参数为true时个表示key重复的时候不覆盖value , 这里为false表示是key重复的时候会覆盖value.
putVal方法中还有扩容的入口在
if (++size > threshold)resize();resize()方法扩容部分关键代码
if (oldCap > 0) {if (oldCap >= MAXIMUM_CAPACITY) {threshold = Integer.MAX_VALUE;return oldTab;}else if ((newCap = oldCap
推荐阅读
- 逍遥浪子龙|汽车“栽进窗”,太危险!女子停车忘拉手刹
- [婚外情]我结婚了但爱上了别人,心存愧疚,我想回归家庭该怎么做
- 足坛最前线|却被国米球迷永远拉黑,布尔迪索:潘帕斯浪子中后卫
- 土土女排|进攻实力将大幅提升,回归家乡!女排世界冠军有望加盟辽宁
- 钱江晚报|老人凌晨买菜…夜班公交司机汤小连:我见过杭城隐秘风景,年轻人半夜归家
- 科技浪子|非蠢即坏,手机欠费超3月上征信?网友:不知道哪个B出的主意
- 科技浪子 非蠢即坏,手机欠费超3月上征信?网友:不知道哪个B出的主意
- 森焱姑娘|涂磊首曝与女儿高清合照:求你们别再劝他复出了,回归家庭6个月
- 浪子林小君|谁才是掌握蜀汉生杀大权的二把手?并非诸葛亮,刘备之下
- 浪子林小君|八王逼宫时,病怏怏的十三爷为啥还能控制兵权?,雍正王朝中
