在jdk1.8之前,Java对于HashMap的实现,并未涉及到红黑树。就常用数据结构中,数组由于索引的存在,具备查询快,增删慢的特性。而链表则具备增删哭,查询慢的特性。二者各有优缺点。运用哲学辩证法的观点来说,HashMap正好集成了这两者中精华的部分。
提起HashMap,往往最先浮现的,键值对,key不允许重复,key允许为null,线程不安全等等...但是谈到实现方式上,可以用拉链法作如下阐述。HashMap的底层实现中,是采用的数组+链表的组合方式(也称哈希表结构),数组中元素后对应绑定的是链表。首先,当向HashMap中put元素时,会先对key进行Hash计算,根据计算后的Hash值转换成数组中的下标,当数组中该下标位置后为空时(无链表),这个(key,value)信息会封装进Node对象中,再将这个Node对象存储在该下标位置后面对应的链表中。当第二次put进新key时,也会先对这个新key对应的Hash值,如果计算出来的Hash值跟原来已有的Hash值相等时,那就会对该下标后面绑定的链表中的每一个node的key做equals比较,如果key一致,会做覆盖处理。如果比对下来key都不一致,就会将该新key对应的Node添加在链表末端。
为什么说HashMap查询快,增删也快?得益于此种Hash表结构,当对HashMap进行查询时,也会对key先做Hash计算,通过Hash值转换的下标,可以直接定位到对应的链表,避免了全部扫描。其二,在对HashMap做增删操作时,都是在链表上进行,链表的空间是松散的,不像数组在某个位置增删时后面元素还需要移位等操作,因此增删较快。
在JDK8之后,考虑到链表长度过长带来的性能问题。引入到了红黑树的处理来提高性能,当链表长度到达一定的阀值会进行红黑树的转换,阀值为8。