Map集合类 | key | value |
HashMap | 允许为null | 允许为null |
TreeMap | 不允许为null | 允许为null |
ConcurrentMap | 不允许为null | 不允许为null |
HashTable | 不允许为null | 不允许为null |
哈希函数有以下计算哈希值的方法:
(1)直接定址法
取关键字或者关键字的某个线性函数为Hash地址,即Hash(key)=a*key+b
(2)除留余数法
如果知道Hash表的最大长度为m,可以取不大于m的最大质数p,然后对关键字进行取余运算,Hash(key)=key%p。
在这里p的选取非常关键,p选择的好的话,能够最大程度地减少冲突,p一般取不大于m的最大质数。
(3)平方取中法
对关键字进行平方运算,然后取结果的中间几位作为Hash地址。假如有以下关键字序列{421,423,436},平方之后的结果为{177241,178929,190096},那么可以取{72,89,00}作为Hash地址。
(4)折叠法
将关键字拆分成几部分,然后将这几部分组合在一起,以特定的方式进行转化形成Hash地址。假如知道图书的ISBN号为8903-241-23,可以将Hash(key)=89+03+24+12+3作为Hash地址。
1、HashMap相关知识点
- 哈希冲突的解决方案有:开放定址法(线性探测法、),再散列函数法,链地址法,而HashMap即是采用了链地址法进行哈希地址冲突的解决方案,也就是数组+链表的方式
- HashMap的主干是一个Entry数组。Entry是HashMap的基本组成单元,每一个Entry包含一个key-value键值对。
- HashMap由数组+链表组成的,数组是HashMap的主体,链表则是主要为了解决哈希冲突而存在的,如果定位到的数组位置不含链表(当前entry的next指向null),那么查找,添加等操作很快,仅需一次寻址即可;如果定位到的数组包含链表,对于添加操作,其时间复杂度为O(n),首先遍历链表,存在即覆盖,否则新增;对于查找操作来讲,仍需遍历链表,然后通过key对象的equals方法逐一比对查找。所以,性能考虑,HashMap中的链表出现越少,性能才会越好。
- JDK1.8在JDK1.7的基础上针对增加了红黑树来进行优化。即当链表超过8时,链表就转换为红黑树,利用红黑树快速增删改查的特点提高HashMap的性能,其中会用到红黑树(相关概念在下方)的插入、删除、查找等算法。
红黑树的一些相关概念:
- 节点是红色或黑色
- 根节点是黑色
- 每个叶子节点都是黑色的空节点(NIL节点)
- 每个红色节点的两个子节点都是黑色。(从每个叶子到根的所有路径上不能有两个连续的红色节点)
- 从任一节点到其每个叶子的所有路径都包含相同数目的黑色节点