当前位置: 首页 > news >正文

JAVA开发(数据类型String和HasMap的实现原理)

在JAVA开发中,使用最多的数据类型恐怕是String 和 HasMap两种数据类型。在开发的过程中我们每天都使用的不亦乐乎。但是相信很多人都没有考虑过String数据类型的实现原理或者说是在数据结构中的存储原理,还有一个就是是HashMap,也很少有人去了解。而且随着jdk版本的发展,这两个类型的实现都一直在优化,而不是一成不变的。有时候只有在找工作面试的时候被面试官问题,然后是一脸蒙蔽。每天都在用,也不用考虑它的原理啊。懂得用不就行了吗?这句话其实对其实也不对,对于实现业务来说,是已经足够了。但是对于对每一行代码做到极致的性能,很多东西还是需要知道它的原理。今天这一节就来梳理梳理String和HashMap的实现原理。

String数据类型:

无处不在的String类型。它位于java jdk 的lang包中,所以无需import就可以直接使用。从源码上看String是被final修饰的,所以它是不能被继承的。

 

	/** ID */private Integer id;/** 用户姓名 */private String userName;/** 登录名 */private String loginName;/** 密码 */private String password;public User() {super();}public User(Integer id, String userName, String loginName, String password) {super();this.id = id;this.userName = userName;this.loginName = loginName;this.password = password;}

由于其使用的广泛性,几乎在每一代的JDK优化升级中都存在对String的优化。

首先在JDK1.7中,我们都知道 String s = "maoheyeren";这个对象是存在常量池中的,JDK1.6的常量池位于方法区。但是到了JDK1.7,就讲常量池优化到了堆中,因为堆的内存更大,方便常量池的扩展。

在JDK1.8和JDK1.8以前,我们可以看一下源码,它的构造函数,可以知道String的下一层是使用char类型存储,但是到了JDK9就使用了byte[]存储,进行了优化减少了存储空间消耗。

 所以就是大家平时天天使用的String类型,也不是一层不变的!这个需要注意,算法的优化永无止境!

String对象的创建方式:

String s = "茅河野人是大神";
String s = new String ("茅河野人是大神")

 

String的源码,实现了序列化、Comparable以及CharSequence接口。

public final class Stringimplements java.io.Serializable, Comparable<String>, CharSequence {// 在JDK1.8中String的值使用char[]数组保存private final char value[];// 使用私有成员变量hash来缓存String的哈希值private int hash; // Default to 0// 构造方法public String(String original) {this.value = original.value;this.hash = original.hash;}public String(char value[]) {this.value = Arrays.copyOf(value, value.length);}...省略
}

 还有一个比较关心的问题String到底能存多长的数据。

查看String源代码返回长度的方法,int类型所能表示的最大范围为[0, 2^31-1],实际根据String的两种创建方式还有所不同。

1、使用String s = "茅河野人是大神";  方式创建对象时javac编译会校验字符串的长度,0xFFFF所能表示的最大长度为2^16=65536,因此这种方式创建的字符串长度会小于65536。而且CONSTANT_Utf8_info型常量的最大长度是是65535 - 1 = 65534个字节,若是中文字符,长度为65535 / 3字节。如果运行时方法区设置的比较小,实际长度可能达不到理论字节。
 

2、使用new关键字创建对象时,对象在堆内存中分配空间,调用系统的copyOf(),方法,所支持的理论最大长度为Integer.MAX_VALUE,2^31-1;实际情况受虚拟机和堆内存的大小限制。

HashMap数据类型:

HaspMap我们天天往里面put东西,put字符串,put对象,用的时候就get出来,也是从来没思考过里面的实现原理。

JDK1.8 之前 HashMap 的数据结构是 数组+链表 。数组是 HashMap 的主体,单向链表则是主要为了解决哈希冲突而存在的(“拉链法”解决冲突)。JDK1.8 以后在解决哈希冲突时有了较大的变化,当链表长度大于等于阈值(默认为 8)时,且tab.length>=64时,将链表转化为红黑树,以减少搜索时间。
 注意,HashMap的底层数据结构中链表是单向链表,也就是只有next指针,没有prev指针。而LinkedHashMap维护了before、 after、head以及tail。

JDK1.8 之前 HashMap 底层是 数组和链表 结合在一起使用也就是 链表散列。HashMap 通过 key 的 hashCode 经过扰动函数处理过后得到 hash 值,然后通过 (n - 1) & hash值 判断当前元素存放的位置(这里的 n 指的是数组的长度)。

如果当前位置存在元素的话,就判断该元素与要存入的元素的 hash 值以及 key 是否相同,如果相同的话,直接覆盖;不相同就通过拉链法解决冲突。

hashcode的计算算法:

hash(Object key)–扰动函数
所谓扰动函数指的就是 HashMap 的 hash 方法。使用 hash 方法也就是扰动函数是为了防止一些实现比较差的 hashCode() 方法造成的碰撞,换句话说使用扰动函数之后可以减少碰撞。

先获得key的hashCode的值 h,然后 h 和 h右移16位 做异或运算。

实质上是把一个数的低16位与他的高16位做异或运算,因为在 (n - 1) & hash 的计算中,hash变量只有末x位会参与到运算。使高16位也参与到hash的运算能减少冲突。

JDK1.7之前的hashMap存储结构:

 

到了JDK1.8以后进行额优化,这一点经常有些找事情的面试官会问到。可以看出HashMap以链表的方式存储在数组中,到了JDK1.8以后,以红黑树的方式存储在数组中。

 

   static class Node<K,V> implements Map.Entry<K,V> {final int hash;final K key;V value;Node<K,V> next;Node(int hash, K key, V value, Node<K,V> next) {this.hash = hash;this.key = key;this.value = value;this.next = next;}public final K getKey()        { return key; }public final V getValue()      { return value; }public final String toString() { return key + "=" + value; }public final int hashCode() {return Objects.hashCode(key) ^ Objects.hashCode(value);}public final V setValue(V newValue) {V oldValue = value;value = newValue;return oldValue;}public final boolean equals(Object o) {if (o == this)return true;if (o instanceof Map.Entry) {Map.Entry<?,?> e = (Map.Entry<?,?>)o;if (Objects.equals(key, e.getKey()) &&Objects.equals(value, e.getValue()))return true;}return false;}}

 

相关文章:

JAVA开发(数据类型String和HasMap的实现原理)

在JAVA开发中&#xff0c;使用最多的数据类型恐怕是String 和 HasMap两种数据类型。在开发的过程中我们每天都使用的不亦乐乎。但是相信很多人都没有考虑过String数据类型的实现原理或者说是在数据结构中的存储原理&#xff0c;还有一个就是是HashMap&#xff0c;也很少有人去了…...

Hbase 映射到Hive

目录 一、环境配置修改 关闭掉hbase&#xff0c;zookeeper和hive服务 进入hive312/conf 修改hive-site.xml配置&#xff0c; 在代码最后添加配置 将hbase235的jar包全部拷贝到hive312的lib目录&#xff0c;并且所有的是否覆盖信息全部输入n&#xff0c;不覆盖 查看hive312下…...

14_MySQL视图

1. 常见的数据库对象2. 视图概述2.1 使用视图的好处视图一方面可以帮我们使用表的一部分而不是所有的表&#xff0c;另一方面也可以针对不同的用户制定不同的查询视图。比如&#xff0c;针对一个公司的销售人员&#xff0c;我们只想给他看部分数据&#xff0c;而某些特殊的数据…...

做程序界中的死神,斩魂刀始解

标题解读&#xff1a;标题中的死神&#xff0c;是源自《死神》动漫里面的角色&#xff0c;斩魂刀是死神的武器&#xff0c;始解是斩魂刀的初始解放形态&#xff0c;卐解是斩魂刀的觉醒解放形态&#xff0c;也是死神的大招。意旨做程序界中程序员的佼佼者&#xff0c;一步一步最…...

顺序表——“数据结构与算法”

各位CSDN的uu们你们好呀&#xff0c;今天小雅兰的内容是数据结构与算法里面的顺序表啦&#xff0c;在我看来&#xff0c;数据结构总体上是一个抽象的东西&#xff0c;关键还是要多写代码&#xff0c;下面&#xff0c;就让我们进入顺序表的世界吧 线性表 顺序表 线性表 线性表&…...

嵌入式Linux从入门到精通之第十六节:U-boot分析

简介 u-boot最初是由PPCBoot发展而来的,可以引导多种操作系统、支持多种架构的CPU,它对PowerPC系列处理器的支持最为完善,而操作系统则对Linux系统的支持最好目前已成为Armboot和PPCboot的替代品。 特点: 主要支持操作系统:Linux、NetBSD、 VxWorks、QNX、RTEMS、ARTOS、L…...

UART 串口通信

第18.1讲 UART串口通信原理讲解_哔哩哔哩_bilibili 并行通信 一个周期同时发送8bit的数据&#xff0c;占用引脚资源多 串行通信 串行通信的通信方式&#xff1a; 同步通信 同一时钟下进行数据传输 异步通信 发送设备和接收设备的时钟不同 但是需要约束波特率&#xff08;…...

【硬件】P沟道和N沟道MOS管开关电路设计

场效应管做的开关电路一般分为两种&#xff0c;一种是N沟道&#xff0c;另一种是P沟道&#xff0c;如果电路设计中要应用到高端驱动的话&#xff0c;可以采用PMOS来导通。P沟道MOS管开关电路PMOS的特性&#xff0c;Vgs小于一定的值就会导通&#xff0c;当Vgs<0,即Vs>Vg,管…...

中移杭研一面经历

文章目录 1、常用的Java元注解@Documented@Target@Retention@Override@Deprecated@Inherited@Repeatable@Native2、Java注解的原理3、spring boot starter开发过程1、原理浅谈2、大概步骤3、项目介绍1、常用的Java元注解 @Documented @Documented 是一个标记注解,没有成员变…...

如何成为一名全栈工程师:专业建议与技能要求

作为一名全栈工程师&#xff0c;你需要拥有跨越前端、后端、数据库等多个领域的技能&#xff0c;并能够将它们整合起来构建出完整的应用程序。因此&#xff0c;成为一名全栈工程师需要你掌握多种技术&#xff0c;具备较强的编程能力和系统设计能力。下面&#xff0c;我将从以下…...

MySQL架构篇

一、进阶学习环境说明 1.1 MySQL服务器环境 Linux虚拟机&#xff1a;CentOS 7 MySQL&#xff1a;MySQL5.7.30 在Linux服务器中安装MySQL&#xff1a; ps.如果有自己的云服务器&#xff0c;可忽略前两步&#xff0c;直接进行第三步 1.2 服务器日志文件说明 MySQL是通过文件系统对…...

Redhat7.6安装weblogic10.3.6(超详细,有图文)

一、环境 linux版本&#xff1a;Redhat 7.6 weblogic版本:WLS10.3.6 jdk版本&#xff1a;jdk1.8.0 下载网址&#xff1a;https://www.oracle.com/technetwork/middleware/weblogic/downloads/index.html 1.安装vsftpd服务&#xff0c;将部署环境使用JDK文件和wls服务文件…...

dashboard疏散主机提示报错:无法疏散主机...处理方法、openstack虚拟机状态卡在重启处理方法、openstack在数据库修改虚拟机状态的方法

文章目录dashboard疏散主机提示报错&#xff1a;无法疏散主机...处理方法报错说明【状态卡在reboot状态】解决方法【登录nova数据库修改虚拟机信息】首先获取nova数据库的密码登录nova数据库并做修改验证信息是否修改成功再次迁移并验证报错说明【虚拟机状态error也会导致疏散失…...

力扣:轮转数组(详解)

前言&#xff1a;内容包括&#xff1a;题目&#xff0c;代码实现&#xff0c;大致思路&#xff0c;代码解读 题目&#xff1a; 给定一个整数数组 nums&#xff0c;将数组中的元素向右轮转 k 个位置&#xff0c;其中 k 是非负数。 示例 1: 输入: nums [1,2,3,4,5,6,7], k 3…...

Vue计算属性Computed

30. Vue计算属性Computed 1. 定义 Computed属性是Vue中的一个计算属性&#xff0c;是一种基于其它属性值计算而来的属性值&#xff0c;具有缓存机制&#xff0c;在依赖的属性值发生变化时会重新计算。 使用computed属性可以避免在模板中书写过多的计算逻辑&#xff0c;提高代…...

实验四:搜索

实验四&#xff1a;搜索 1.填格子 题目描述 有一个由数字 0、1 组成的方阵中&#xff0c;存在一任意形状的封闭区域&#xff0c;封闭区域由数字1 包围构成&#xff0c;每个节点只能走上下左右 4 个方向。现要求把封闭区域内的所有空间都填写成2 输入要求 每组测试数据第一…...

本地开发vue项目联调遇到访问接口跨域问题

本地开发vue项目联调遇到访问接口跨域问题 修改本地的localhost 一&#xff1a;按winr打开运行窗口&#xff0c;输入drivers &#xff0c;然后回车 二&#xff1a;打开etc文件夹&#xff0c;然后用记事本的方式打开里面的hosts文件&#xff0c; 三&#xff1a;这时我们就可…...

Vue键盘事件的使用

前言 在vue中&#xff0c;我们经常会用到键盘事件&#xff0c;不管是我们按下某个键&#xff0c;其实都是一次键盘事件的调用&#xff0c;下面就介绍下Vue中的键盘事件 先写一段代码&#xff0c;这里我选择的键盘事件是keyup,当然用keydown也是没问题的 问题来了&#xff0c;…...

抓包工具fiddler详细使用教程

各位做测试的同学想必对抓包工具fiddler并不陌生&#xff0c;但是很多同学可能没有总结过它的用法&#xff0c;下面我总结了fiddler一些常用的用法。 Web端抓包配置 打开Fiddler&#xff0c;Tools -> Fiddler Options -> HTTPS 配置完后记得要重启Fiddler 选中Decrpt …...

raspberry Pi 连接蓝牙(小爱同学)

参数valueraspberry pi MOdel4B&#xff0c;4Gbbluetooth MOdel小爱同学writeTime2023年 2月11日 下午13&#xff1a;14分raspberry System ModelLinux raspberrypi 5.15.61-v8 #1579 SMP PREEMPT Fri Aug 26 11:16:44 BST 2022 aarch64 GNU/Linux 连接蓝牙 请在小爱同学app上…...

Vue3 + Element Plus + TypeScript中el-transfer穿梭框组件使用详解及示例

使用详解 Element Plus 的 el-transfer 组件是一个强大的穿梭框组件&#xff0c;常用于在两个集合之间进行数据转移&#xff0c;如权限分配、数据选择等场景。下面我将详细介绍其用法并提供一个完整示例。 核心特性与用法 基本属性 v-model&#xff1a;绑定右侧列表的值&…...

QMC5883L的驱动

简介 本篇文章的代码已经上传到了github上面&#xff0c;开源代码 作为一个电子罗盘模块&#xff0c;我们可以通过I2C从中获取偏航角yaw&#xff0c;相对于六轴陀螺仪的yaw&#xff0c;qmc5883l几乎不会零飘并且成本较低。 参考资料 QMC5883L磁场传感器驱动 QMC5883L磁力计…...

三体问题详解

从物理学角度&#xff0c;三体问题之所以不稳定&#xff0c;是因为三个天体在万有引力作用下相互作用&#xff0c;形成一个非线性耦合系统。我们可以从牛顿经典力学出发&#xff0c;列出具体的运动方程&#xff0c;并说明为何这个系统本质上是混沌的&#xff0c;无法得到一般解…...

Axios请求超时重发机制

Axios 超时重新请求实现方案 在 Axios 中实现超时重新请求可以通过以下几种方式&#xff1a; 1. 使用拦截器实现自动重试 import axios from axios;// 创建axios实例 const instance axios.create();// 设置超时时间 instance.defaults.timeout 5000;// 最大重试次数 cons…...

ardupilot 开发环境eclipse 中import 缺少C++

目录 文章目录 目录摘要1.修复过程摘要 本节主要解决ardupilot 开发环境eclipse 中import 缺少C++,无法导入ardupilot代码,会引起查看不方便的问题。如下图所示 1.修复过程 0.安装ubuntu 软件中自带的eclipse 1.打开eclipse—Help—install new software 2.在 Work with中…...

初学 pytest 记录

安装 pip install pytest用例可以是函数也可以是类中的方法 def test_func():print()class TestAdd: # def __init__(self): 在 pytest 中不可以使用__init__方法 # self.cc 12345 pytest.mark.api def test_str(self):res add(1, 2)assert res 12def test_int(self):r…...

浪潮交换机配置track检测实现高速公路收费网络主备切换NQA

浪潮交换机track配置 项目背景高速网络拓扑网络情况分析通信线路收费网络路由 收费汇聚交换机相应配置收费汇聚track配置 项目背景 在实施省内一条高速公路时遇到的需求&#xff0c;本次涉及的主要是收费汇聚交换机的配置&#xff0c;浪潮网络设备在高速项目很少&#xff0c;通…...

LINUX 69 FTP 客服管理系统 man 5 /etc/vsftpd/vsftpd.conf

FTP 客服管理系统 实现kefu123登录&#xff0c;不允许匿名访问&#xff0c;kefu只能访问/data/kefu目录&#xff0c;不能查看其他目录 创建账号密码 useradd kefu echo 123|passwd -stdin kefu [rootcode caozx26420]# echo 123|passwd --stdin kefu 更改用户 kefu 的密码…...

人机融合智能 | “人智交互”跨学科新领域

本文系统地提出基于“以人为中心AI(HCAI)”理念的人-人工智能交互(人智交互)这一跨学科新领域及框架,定义人智交互领域的理念、基本理论和关键问题、方法、开发流程和参与团队等,阐述提出人智交互新领域的意义。然后,提出人智交互研究的三种新范式取向以及它们的意义。最后,总结…...

【C++进阶篇】智能指针

C内存管理终极指南&#xff1a;智能指针从入门到源码剖析 一. 智能指针1.1 auto_ptr1.2 unique_ptr1.3 shared_ptr1.4 make_shared 二. 原理三. shared_ptr循环引用问题三. 线程安全问题四. 内存泄漏4.1 什么是内存泄漏4.2 危害4.3 避免内存泄漏 五. 最后 一. 智能指针 智能指…...