HashMap和TreeMap总结

一、哈希表是如何添加数据

  1. 计算哈希码(调用hashCode(),结果是一个int值,整数的哈希码取自身即可)

  2. 计算在哈希表中的存储位置 y=k(x)=x%11

    x:哈希码 k(x) 函数y:在哈希表中的存储位置

  3. 存入哈希表

    情况1:一次添加成功

    情况2:多次添加成功(出现了冲突,调用equals()和对应链表的元素进行比较,比较到最后,结果都是false,创建新节点,存储数据,并加入链表末尾)

    情况3:不添加(出现了冲突,调用equals()和对应链表的元素进行比较, 经过一次或者多次比较后,结果是true,表明重复,不添加)

结论1:哈希表添加数据快(3步即可,不考虑冲突)

结论2:唯一、无序

注意:Object中的hashCode()方法是根据对象在内存中的地址计算得出。所以一般我们的自定义类型要重写hashCode()方法。

哈希冲突/哈希碰撞:原内容不一样,经过hash计算后得到的结果一样的,这种情况称为hash碰撞。

二、解决哈希碰撞的方法

1. 链地址法(hashmap就是这样处理的)重点

        把Hash表的每个单元作为链表的头节点。当发生冲突时放入到同一个hash值对应的链表。

2. 开放定址法

        发生冲突后寻找下一个hash地址。

3. 再次哈希法

        对hash值再次进行hash计算

4. 建立公共溢出区

        把hash表分为基本表和溢出表。当溢出时放入到溢出表中。

三、负载因子/装填因子/加载因子

1. 装填因子 = 表中的记录数 / 哈希表的长度,例如: 4/ 16 =0.25   8/ 16=0.5

2. 表示:如果装填因子越小,表明表中还有很多的空单元,则添加发生冲突的可能性越小;而装填因子越大,则发生冲突的可能性就越大,在查找时所耗费的时间就越多。 有相关文献证明当装填因子在0.5左右时候,Hash性能能够达到最优。

3. 结论:因此,一般情况下,装填因子取经验值0.5,但是频繁扩容又会降低效率,所以java中的HashMap默认用的0.75

4. 原因:如果Hash表的空间远远大于最后实际存储的记录个数,则造成了很大的空间浪费, 如果选取小了的话,则容易造成冲突。 在实际情况中,一般需要根据最终记录存储个数和关键字的分布特点来确定Hash表的大小。还有一种情况时可能事先不知道最终需要存储的记录个数,则需要动态维护Hash表的容量,此时可能需要重新计算Hash地址。

四、常见面试题

从Java8开始HashMap底层由数组+链表变成数组+链表+红黑树。

使用HashMap时,当使用无参构造方法实例化时,设置扩容因子为默认扩容因子0.75。

当向HashMap添加内容时,会对Key做Hash计算,把得到的Hash值和数组长度-1按位与,计算出存储的位置。

如果数组中该没有内容, 直接存入数组中(Node节点对象), 该下标中有Node对象了, 把内容添加到对应的链表或红黑树中。

如果添加后链表长度大于等于8,会判断数组的长度是否大于等于64,如果小于64对数组扩容,扩容长度为原长度的2倍,扩容后把原Hash表内容重新放入到新的Hash表中。如果Hash长度大于等于64会把链表转换红黑树。

最终判断HashMap中元素个数是否已经达到扩容值(threshold),如果达到扩容值,需要进行扩容,扩容一倍。

反之,如果删除元素后,红黑树的元素个数小于等于6,由红黑树转换为链表。

五、TreeMap特点

[1]每个节点都只能是红色或者黑色。

[2]根节点是黑色。

[3]每个叶节点(NIL节点,NULL空节点)是黑色的。

[4]每个红色节点的两个子节点都是黑色 (从每个叶子到根的路径上不会有两个连续的红色节点) 。

[5]从任一节点到其每个叶子的所有路径都包含相同数目的黑色节点。

六、红黑树插入时的七种情况情况

【情况一】为根节点

若新插入的节点N没有父节点,则直接当做根据节点插入即可,同时将颜色设置为黑色。

【情况二】父结点为黑色

那么插入的红色节点将不会影响红黑树的平衡,直接插入即可。

【情况三】父节点和叔节点都为红色

当叔父结点为红色时,无需进行旋转操作,只要将父和叔结点变为黑色,将祖父结点变为红色即可

但是经过上面的处理,可能G节点的父节点也是红色,这个时候我们需要将G节点当做新增节点递归处理。

 

【情况四】父红,叔黑,并且新增节点和父节点都为左子树

对于这种情况先已P节点为中心进行右旋转,在旋转后产生的树中,节点P是节点N、G的父节点。

但是这棵树并不规范,所以我们将P、G节点的颜色进行交换,使之其满足规范。(这个位置的U可能不存在,因为NULL节点也是黑色)

 

【情况五】父红,叔黑,并且新增节点和父节点都为右子树

对于这种情况先已P节点为中心进行左旋转,在旋转后产生的树中,节点P是节点G、N的父节点。但是这棵树并不规范,所以我们将P、G节点的颜色进行交换,使之其满足规范。

 

【情况六】父红,叔黑,并且新增节点为左子树,父节点为右子树

对于这种情况先以N节点为中心进行右旋转,在旋转后产生的树中,节点N是节点P、X的父节点。然后再以N节点为中心进行左旋转,在旋转后产生的树中,节点N是节点P、G的父节点。但是这棵树并不规范,所以我们将N、G节点的颜色进行交换,使之其满足规范。

 

【情况七】父红,叔黑,并且新增节点为右子树,父节点为左子树

对于这种情况先以N节点为中心进行左旋转,在旋转后产生的树中,节点N是节点P、Y的父节点。然后再以N节点为中心进行右旋转,在旋转后产生的树中,节点N是节点P、G的父节点。但是这棵树并不规范,所以我们将N、G节点的颜色进行交换,使之其满足规范。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值