Hashtable底层原理分析

news2024/9/29 13:21:06

特点

1、存放k-v键值对
2、key\value均不能是null,否则会抛出空指针异常NullPointerException
3、线程安全的,底层使用synchronized

高频问题

1、初始化大小多少?什么时候初始化? 答:默认11,在第一次put的时候初始化
2、什么情况下扩容?扩多大? 答:Hashtable中数据大于数组长度*负载因子(舍弃小数)时,扩容一倍再加1。例如初始化为11,第一次扩容后为11✖️2+1=23

jdk8源码分析

初始化

在这里插入图片描述

// 无参
Hashtable hashtable1 = new Hashtable();
// 指定初始化数组大小
Hashtable hashtable2 = new Hashtable(11);
// 指定初始化数组大小 负载因子
Hashtable hashtable3 = new Hashtable(11,0.75f);
// map
Hashtable hashtable4 = new Hashtable(hashtable1);

与Hashmap不同,Hashtable在new的时候就直接就初始化了

参数说明

// 存放元素
private transient Entry<?,?>[] table;
// table内元素个数
private transient int count;
// 阈值
private int threshold;
// 负载因子
private float loadFactor;
// 操作次数
private transient int modCount = 0;

put源码分析

1、synchronized修饰,保证多线程安全
2、value为null,抛出异常

public synchronized V put(K key, V value) {
    // value为null,抛出异常
    if (value == null) {
        throw new NullPointerException();
    }

    Entry<?,?> tab[] = table;
    int hash = key.hashCode();
    int index = (hash & 0x7FFFFFFF) % tab.length;
    @SuppressWarnings("unchecked")
    Entry<K,V> entry = (Entry<K,V>)tab[index];
    // 存在时直接覆盖 并返回修改前的值
    for(; entry != null ; entry = entry.next) {
        if ((entry.hash == hash) && entry.key.equals(key)) {
            V old = entry.value;
            entry.value = value;
            return old;
        }
    }
	// 存放元素
    addEntry(hash, key, value, index);
    return null;
}

addEntry(添加元素)源码分析

 private void addEntry(int hash, K key, V value, int index) {
 	// 操作次数
    modCount++;

    Entry<?,?> tab[] = table;
    // table内元素个数大于等于阈值扩容
    // 默认数组大小是11,负载因子为0.75 阈值=11*0.75=8
    // 插入第九条时 count=8 进入扩容方法 count是在方法最好做的++操作
    if (count >= threshold) {
        // 扩容
        rehash();

        tab = table;
        hash = key.hashCode();
        index = (hash & 0x7FFFFFFF) % tab.length;
    }

    // 先找到index下标原数据
    @SuppressWarnings("unchecked")
    Entry<K,V> e = (Entry<K,V>) tab[index];
    // 新数据的next节点为原数据 头插法,然后把新数据放入数组中
    // Entry(int hash, K key, V value, Entry<K,V> next)
    tab[index] = new Entry<>(hash, key, value, e);
    // table内元素个数+1
    count++;
}

rehash(扩容)源码分析

protected void rehash() {
	// 老数组容量
    int oldCapacity = table.length;
    // 老元素
    Entry<?,?>[] oldMap = table;

    // 扩容大小=老数组容量*2+1
    int newCapacity = (oldCapacity << 1) + 1;
    // 判断是否超过最大值
    if (newCapacity - MAX_ARRAY_SIZE > 0) {
        if (oldCapacity == MAX_ARRAY_SIZE)
            // Keep running with MAX_ARRAY_SIZE buckets
            return;
        newCapacity = MAX_ARRAY_SIZE;
    }
    // new一个新的数组,容量为扩容后的容量
    Entry<?,?>[] newMap = new Entry<?,?>[newCapacity];

    modCount++;
    // 阈值 
    threshold = (int)Math.min(newCapacity * loadFactor, MAX_ARRAY_SIZE + 1);
    table = newMap;
	// 循环老数组
    for (int i = oldCapacity ; i-- > 0 ;) {
    	// 循环链表
        for (Entry<K,V> old = (Entry<K,V>)oldMap[i] ; old != null ; ) {
            Entry<K,V> e = old;
            old = old.next;
			// 重新计算下标
            int index = (e.hash & 0x7FFFFFFF) % newCapacity;
            e.next = (Entry<K,V>)newMap[index];
            // 放入新数组内
            newMap[index] = e;
        }
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/353598.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

流量主开通一周,收益55块了,周末可以加个鸡腿!记录一下我开通流量主到有收益的艰难过程!

文章目录公众号【字节卷动】账号历程注册写文冻结解冻漫无目的的写作重新出发大佬带我憧憬申请流量主失败腾讯客服有人工吗&#xff1f;白高兴一场流量主正式开通全力开干付出总有回报总结公众号【字节卷动】账号历程 注册 其实在2017年1月我就注册了公众号&#xff0c;但是一…

【网络原理5】IP协议篇

目录 IP协议报头 4位版本号 4位首部长度 8位服务类型(TOS) 16位总长度 IP拆包 16位标识、3位标志、13位片偏移​编辑 8位生存时间(TTL) 8位协议 16位首部校验和 网络地址管理 32位源ip&32位目的ip 方案一:动态分配ip地址 方案2:NAT网络地址转换(使用一个ip代…

docker中安装Mariadb

一、 docker中下载mariadb我的安装的版本是10.1.21&#xff0c;&#xff08;大家可以根据自己的需求制定版本&#xff09;docker pull mariadb:10.1.21 二、新建一个目录作为容器的映射目录新建目录用来将容器的目录及数据挂载到该目录下mkdir -p /data/mariadb/data 三、启动m…

Java反序列化漏洞——CommonsCollections1链分析

CC1的链在jdk-8u71之后因为AnnotationInvocationHandler的修改已无法利用。一、TransformedMap基于jdk-8u65进行试验1.Rutime.getRuntime().exec()Runtime.getRuntime().exec("calc");2.Runtime类不允许序列化&#xff0c;所有需要调用反射进行命令执行&#xff0c;将…

无需经验的steam搬砖,每天操作1小时,轻松创业赚钱!

我作为一个95后社畜&#xff0c;就喜欢倒腾各种赚钱的事情&#xff0c;8年老韭菜告诉你&#xff0c;副业创收一点都不难&#xff0c;难就难在是否找对项目&#xff0c;俗话说方向不对&#xff0c;努力白费&#xff01; 什么做苦力、技能、直播卖货&#xff0c;电商等等对比我这…

面试题59 - II. 队列的最大值

题目 请定义一个队列并实现函数 max_value 得到队列里的最大值&#xff0c;要求函数max_value、push_back 和 pop_front 的均摊时间复杂度都是O(1)。 若队列为空&#xff0c;pop_front 和 max_value 需要返回 -1 思路 对于一个普通队列&#xff0c;push_back 和 pop_front…

ChatGPT 简介

目录1 背景与发展历程1.1 背景1.2 发展历程2 技术原理2.1 第一阶段&#xff1a;训练监督策略模型2.2 第二阶段&#xff1a;训练奖励模型2.3 第三阶段&#xff1a;采用强化学习来增强模型的能力。3 国内使用情况及应用的领域4 面临的数据安全挑战与建议4.1 ChatGPT获取数据产生的…

传奇SF架设问题处理方式

传奇SF架设问题处理方式 正常开服当中我们会遇到很多问题&#xff0c;比如游戏黑屏、登录器链接失败等等。 接下来我会把经常会遇到的问题罗列出来以及解决方法附上 传奇M2引擎出现时间格式报错&#xff1f; 这个解决方法有两种第一种是在你电脑桌面的右下角修改时间格式为短…

开源堡垒机GateOne安装

GateOne 是一款基于 html5 实现的 ssh 客户端&#xff0c;有如下特点&#xff1a;不需要任何浏览器插件支持多用户和多终端&#xff0c;同时支持上百个用户和终端终端支持高级特性&#xff0c;例如 256 色彩&#xff0c;高级文本样式支持支持终端截图&#xff0c;保存为图片和 …

【Oracle实用小技巧一】

PLSQL里一些实用的小技巧&#xff0c;可以让日常工作更便捷。 1、PLSQL可以直接打开命令行测试语句&#xff0c;非常方便&#xff0c;可以在SQL窗口里测试好语句&#xff0c;再在SQL文件里编写查询脚本。 2、describe tablename查询数据表结构&#xff1b; 3、upper(text)字…

Yakit实战技巧:用MITM热加载任意修改流量

背景 用户在使用 Yakit MITM 功能的时候&#xff0c;经常会遇到一些特殊需求&#xff1a; 我的数据包需要携带一些特征变量才能访问&#xff0c;但是浏览器无法做到&#xff0c;我可以批量修改流量新增某一个 Header 吗&#xff1f; 我可以在代理层面在所有流量中新增一个参数…

L1-072 刮刮彩票

“刮刮彩票”是一款网络游戏里面的一个小游戏。如图所示&#xff1a; 每次游戏玩家会拿到一张彩票&#xff0c;上面会有 9 个数字&#xff0c;分别为数字 1 到数字 9&#xff0c;数字各不重复&#xff0c;并以 33 的“九宫格”形式排布在彩票上。 在游戏开始时能看见一个位置上…

JavaEE——MyBatis配置文件的详细介绍

简单介绍&#xff1a; 需要我们编写的配置文件主要有三个&#xff0c;分别是核心配置文件&#xff08;mybatis-config.xml&#xff09;&#xff0c;数据库连接信息文件&#xff08;db.properties&#xff09;&#xff0c;SQL语句映射文件&#xff08;Mappers&#xff09;&…

蒙特卡洛方法

蒙特卡洛方法 理解&#xff1a;是一种利用大量样本与样本中正确数量形成的概率去逼近真实值的一种方法。 可以很巧妙的求取某些问题&#xff1a;如 π 的值 1、利用蒙特卡洛方法求π 我们知道圆的面积公式是&#xff1a;π * r * r 那么 1 / 4 圆的面积就是 1/ 4 *π * r …

Spring Data JPA关于懒加载的那些事

背景 环境 相关环境配置&#xff1a; SpringBootPostGreSQL Spring Data JPA 懒加载现象 首先声明一下 application.yml 文件中关于 JPA 的配置&#xff1a; spring:jpa:show-sql: truehibernate:ddl-auto: noneopen-in-view: falseproperties:hibernate:order_by:defaul…

「6」线性代数(期末复习)

&#x1f680;&#x1f680;&#x1f680;大家觉不错的话&#xff0c;就恳求大家点点关注&#xff0c;点点小爱心&#xff0c;指点指点&#x1f680;&#x1f680;&#x1f680; 目录 第五章 相似矩阵及二次型 &2&#xff09;方阵的特征值与特征向量 &3&#xff…

从transformers开始,哪些工作可以被看成是自然语言处理里程碑式的突破。

文本生成的含义是在某一语言数据基础上对语言的从前到后&#xff08;自监督本身下行目标&#xff09;、两段对齐语言序列&#xff08;相互之间的文本共性矩阵计算&#xff09;分布的研究实现路线。简而言之如何以具有可微可导的向量去寻找攻关语言分布的能力即为当代信息科学与…

Springcloud 集成 Seata1.5.2

一、关于seata1.5.2的安装部署请参考&#xff1a; Seata1.5.2安装配置部署_不知道取啥昵称的博客-CSDN博客 二、springcloud程序集成seata 我这里使用的alibaba-cloud版本为 2.2.6.RELEASE&#xff0c;其对应的seata版本为1.3.0&#xff0c;但是想使用seata1.5.2的版本&…

MongoDB-查找表里面重复的记录

一、背景 项目中使用的是mongodb数据库&#xff0c;在测试数据入库的时候&#xff0c;会根据源数据&#xff0c;然后生成一个自增的id到数据库里面&#xff0c;然后线上和测试环境针对同一条数据的id是不一致的。某些数据又只有id与线上匹配上的时候&#xff0c;才能关联上更多…

CentOS 7转化系统为阿里龙蜥Anolis OS 7

转载&#xff1a;原社区CentOS 7迁移Anolis OS 7迁移手册 一、注意事项 Anolis OS 7生态上和依赖管理上保持跟CentOS7.x兼容&#xff0c;一键式迁移脚本centos2anolis.py&#xff0c;实现CentOS7.x到Anolis OS 7的平滑迁移。 使用迁移脚本前需要注意如下事项&#xff1a; 迁…