1.概念
HashMap是基于哈希表的Map接口的非同步实现。此实现提供所有可选的映射操作,并允许使用null值和null键。HashMap储存的是键值对,HashMap很快。此类不保证映射的顺序,特别是它不保证该顺序恒久不变。
此实现假定哈希函数将元素适当地分布在各桶之间,可以为基本操作(get和put)提供稳定的性能。迭代collection视图所需的时间与hashMap实例的“容量”(桶的数量)及大小(键-值映射关系数)的和成正比。所以,如果迭代性能很重要,则不要将初始容量设置得太高(或将加载因子设置得太低),最大限度的降低rehash操作次数。
2.重要参数
HashMap实例有两个参数影响其性能:①初始容量 ②加载因子;
①初始容量----容量是哈希表中桶的数量,初始容量是哈希表在创建时的容量。
②加载因子----当前容量×加载因子=当前哈希表中最多存储的条目数。当哈希表中的数量超出后,则要对该哈希表进行rehash操作(重建内部数据结构,即扩容),扩容到2倍的桶数。
默认哈希表为101,加载因子为0.75.
3.结构理解
HashMap实际上是一个“链表散列”的数据结构,即数组和链表的结合体。
数组:存储区间连续,占用内存严重,寻址容易,插入删除困难;
链表:存储区间离散,占用内存比较宽松,寻址困难,插入删除容易;
Hashmap综合应用了这两种数据结构,实现了寻址容易,插入删除也容易。
hashMap的结构示意图如下:
4.HashMap具体的存取过程
①put键值对
②get值方法的过程
1、指定key 通过hash函数得到key的hash值
int hash=key.hashCode();
2、调用内部方法 getNode(),得到桶号(一般都为hash值对桶数求模)
int index =hash%Entry[].length;
3、比较桶的内部元素是否与key相等,若都不相等,则没有找到。相等,则取出相等记录的value。
4、如果得到 key 所在的桶的头结点恰好是红黑树节点,就调用红黑树节点的 getTreeNode() 方法,否则就遍历链表节点。getTreeNode 方法使通过调用树形节点的 find()方法进行查找。由于之前添加时已经保证这个树是有序的,因此查找时基本就是折半查找,效率很高。
5、如果对比节点的哈希值和要查找的哈希值相等,就会判断 key 是否相等,相等就直接返回;不相等就从子树中递归查找。
HashMap中直接地址用hash函数生成;解决冲突,用比较函数解决。如果每个桶内部只有一个元素,那么查找的时候只有一次比较。当许多桶内没有值时,许多查询就会更快了(指查不到的时候)。