「源码分享」java代码还原HashMap链表和红黑树真实数据存储结构

目录

一、前言

二、模拟流程

1、效果图

链表结构

红黑树结构

2、源码解析

3、设计思路

4、代码模拟

4.1运行代码

4.2 修改hashcode

4.3 红黑树生成


一、前言

首先说下演示流程及设计思路。

JDK1.8版本以上,HashMap在存储数据时,数据格式有两周,一个是链表,一个是红黑树本篇就HashMap的数据存储结构到底怎样,进行模拟和还原。

二、模拟流程

1、效果图

链表结构

 

红黑树结构

以上是跟踪HashMap中的数据存储格式,真实还原底层数据存储结构。 

2、源码解析

效果图已经展示链表和红黑树的数据存储结构,下面我们进行设计。

查看HashMap源码,HashMap中随着数据增多,会自行扩容,直到扩容到64位时会进行红黑树转换。

/**
 * The smallest table capacity for which bins may be treeified.
 * (Otherwise the table is resized if too many nodes in a bin.)
 * Should be at least 4 * TREEIFY_THRESHOLD to avoid conflicts
 * between resizing and treeification thresholds.
 */
static final int MIN_TREEIFY_CAPACITY = 64;

3、设计思路

设计一个类,例如MyMap,分三种场景向HashMap中put数据

  • 正常循环6次向HashMap中添加MyMap
  • 重写MyMap里的hashCode()方法,返回固定值1,循环6次添加到HashMap中
  • 重写MyMap里的hashCode()方法,返回固定值1,循环12次添加到HashMap中

模拟如下:

package com.zhufeng.test;

import java.util.HashMap;
import java.util.Map;

/**
 * @ClassName: ShowHashMapData
 * @Description 还原hashmap数据存储格式
 * @author 月夜烛峰
 * @date 2022/8/30 13:33
 */
public class ShowHashMapData {

    static Map<MyMap, String> map = new HashMap<MyMap, String>(8);

    public static void main(String[] args) throws InterruptedException {

        for (int i = 1; i < 6; i++) {
            MyMap m = new MyMap();
            map.put(m, "value-"+i);
        }
        System.out.println("======数据添加完成======");
        //等待jmap导出dump数据
        Thread.sleep(100*1000);
    }
}
class MyMap{
//    @Override
//    public int hashCode() {
//        return 1;
//    }
//
//    @Override
//    public boolean equals(Object obj) {
//        return false;
//    }
}

4、代码模拟

4.1运行代码

运行以上代码,控制台打印数据添加完成时,导出dump数据

命令:jmap -dump:file=dump-0.hprof,format=b pid

找到运行的java的pid,导出后,通过jhat查看

命令:jhat dump-0.hprof

浏览器访问 localhost:7000

可通过浏览器访问dump解析的数据

这时,HashMap中存储的数据格式是这个样子

点击其中一个,比如第7个,看一看到数据信息

 

这里value-2就是我们put的value值,next不为空,代表当前链表中有下一个节点,可以继续点击,可以查看下一节点的信息。

4.2 修改hashcode

放开代码中注释的内容,重写了两个方法,一个时hashcode(),一个时equals()。

目的是每次返回的hashcode都设置为1,并且通过equals()方法告知JVM是不同的对象。

看下效果:

所有的对象都被归到了hashcode为1的链表中,此时对象类型为Node,这也就是文章开篇的图一链表结构。

4.3 红黑树生成

修改for循环次数:

for (int i = 1; i < 12; i++) {
    MyMap m = new MyMap();
    map.put(m, "value-"+i);
}

再次运行代码:

这里数组个数扩容为64个,节点类型也由Node变为TreeNode,点击查看对象信息

 

TreedNode继承Node,所以类信息中带有Node的属性,主要看left、parent、right三个节点,parent为null代表当前节点为根节点,点击链接跟踪,即可还原出开篇图二的红黑树数据结构。 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

月夜烛峰

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值