电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

您的位置:首頁技術(shù)文章
文章詳情頁

詳解Java中的hashcode

瀏覽:107日期:2022-08-13 10:55:27
一、什么是hash

Hash,一般翻譯做散列、雜湊,或音譯為哈希,是把任意長(zhǎng)度的輸入(又叫做預(yù)映射pre-image)通過散列算法變換成固定長(zhǎng)度的輸出,該輸出就是散列值。這種轉(zhuǎn)換是一種壓縮映射,也就是,散列值的空間通常遠(yuǎn)小于輸入的空間,不同的輸入可能會(huì)散列成相同的輸出,所以不可能從散列值來確定唯一的輸入值。簡(jiǎn)單的說就是一種將任意長(zhǎng)度的消息壓縮到某一固定長(zhǎng)度的消息摘要的函數(shù)。

這個(gè)說的有點(diǎn)官方,你就可以把它簡(jiǎn)單的理解為一個(gè)key,就像是map的key值一樣,是不可重復(fù)的。

二、hash有什么用?,在什么地方用到?

1.在散列表

2.map集合

此處只是做了一個(gè)簡(jiǎn)單的介紹,其實(shí)遠(yuǎn)遠(yuǎn)沒有那么簡(jiǎn)單,如算法里面的散列表,散列函數(shù),以及map的一個(gè)不可重復(fù)到底是怎么樣去判斷的,以及hash沖突的問題,都與hash值離不開關(guān)系。

三、java中String類的hashcode方法

public int hashCode() {int h = hash;if (h == 0 && value.length > 0) { char val[] = value; for (int i = 0; i < value.length; i++) {h = 31 * h + val[i]; } hash = h;}return h; }

可以看到,String類的hashcode方法是通過,char類型的方式進(jìn)行一個(gè)相加,因?yàn)镾tring類的底層就是通過char數(shù)組來實(shí)現(xiàn)的。

如:String str='ab'; 其實(shí)就是一個(gè)char數(shù)組 char[] str={’a’,’b’};

如:字符串 String star=“ab”;那么他對(duì)應(yīng)的hash值就是:3105

怎么算出來的呢?

val[0]=’a’ ; val[1]=’b’

a對(duì)應(yīng)的Ascall碼值為:97b對(duì)的Ascall碼值為:98那么經(jīng)過如下代碼的循環(huán)相加

for (int i = 0; i < value.length; i++) { h = 31 * h + val[i];}

得出:97*31+98=3105;

我們?cè)倏矗?int h = hash;這一個(gè)代碼,為什么有時(shí)候調(diào)用hashcode方法返回的hash值是負(fù)數(shù)呢?

因?yàn)槿绻@個(gè)字符串很長(zhǎng)?那么h的值就會(huì)超過int類型的最大值,有沒有想過,如果一個(gè)int類型的最大值,超過他的范圍之后會(huì)怎么樣呢?

我們先來看這樣一個(gè)簡(jiǎn)單的代碼:

int count=0; while (true){ if (count++<10){ System.out.println('hello world'); } }

大家認(rèn)為hello world會(huì)輸出多少次呢?正常情況來說count小于10就不會(huì)輸出了對(duì)么?但是其實(shí)并不是這樣的,很明確的告訴大家,這是一個(gè)死循環(huán)。

因?yàn)閏ount一直加,最開始if成立,到后面的if不成立,再到后面if會(huì)再次成立,為什么會(huì)成立呢?因?yàn)閏ount變?yōu)榱素?fù)數(shù)。

???? 為什么?因?yàn)閏ount一直無限制的加,由于是線性增長(zhǎng),計(jì)算速度是非常快的,所以,要不了多久,就會(huì)超出int類型的最大值。控制輸出的count變?yōu)榱素?fù)數(shù),所以呢此時(shí)的if條件又成立了。

詳解Java中的hashcode

首先我們來看下int的范圍 :int 為4個(gè)字節(jié),一個(gè)字節(jié)為8位,一個(gè)int值是需要的存儲(chǔ)空間是32位,但是呢?這是一個(gè)有符號(hào)位的int,需要一個(gè)符號(hào)位來表示正數(shù)和負(fù)數(shù),int值的范圍就是:-2^31 ~ 2^31 也就是:-2147483648 到2147483647

我們來看下int最大值對(duì)應(yīng)的二進(jìn)制位是對(duì)少?

詳解Java中的hashcode

全是1? 2147483647最大值不是一個(gè)正數(shù)么?難道第一位難道不是應(yīng)該用0表示么?

此時(shí)這個(gè)0他是省略掉了沒寫的,由于二進(jìn)制系統(tǒng)是通過補(bǔ)碼來保存數(shù)據(jù)的。第一位是符號(hào)位,0為正,1為負(fù),當(dāng)正的除了符號(hào)位全為1,再加1就進(jìn)位了,符號(hào)位就會(huì)變成1,是負(fù)數(shù),其他為0。所以說當(dāng)int的最大值加一個(gè)1,就變?yōu)榱耍钚≈?/p>

來!口說無憑,沒有說服力,我們直接來看代碼:

詳解Java中的hashcode

那么我們?cè)诜催^來想,最小值減1呢?那是不是就是對(duì)對(duì)應(yīng)的是我們int類型的最大值了呀?

認(rèn)真仔細(xì)的看完這個(gè),你就知道為什么hashcode方法調(diào)用的時(shí)候有時(shí)候是正數(shù),有時(shí)候是負(fù)數(shù)了吧?所以說底層還是很有意思的,比如往后做大數(shù)據(jù)開發(fā),那么肯定是需要深入理解這些數(shù)據(jù)類型的范圍,以及他的一個(gè)變化規(guī)則,否則有時(shí)候不知不覺的就犯錯(cuò)了,你還不知道錯(cuò)誤在那兒?嚴(yán)重的話就是會(huì)損失精度,導(dǎo)致結(jié)果和你預(yù)期的結(jié)果相差甚遠(yuǎn)。就因?yàn)榧恿藗€(gè)1,就導(dǎo)致結(jié)果和預(yù)期結(jié)果相差十萬八千里。

這是String類的hashcode方法的一個(gè)具體實(shí)現(xiàn)過程。

四、兩個(gè)對(duì)象的 hashCode()相同,則 equals()也一定為 true,對(duì)嗎?

首先呢?這個(gè)肯定是不對(duì)的。

因?yàn)檫@兩個(gè)方法都可以重寫,如果是自己的類,那么可以靈活重寫,如果是jdk自己的類,那就要看他到底有沒有重寫這兩個(gè)方法。

我們以String類的equlas方法為例:我們都知道,如果equlas方法如果沒有重寫,那就繼承Object類的equlas方法,默認(rèn)比較的是兩個(gè)對(duì)象的內(nèi)存地址,如果重寫了,那就根據(jù)我們自己重寫的規(guī)則來比較兩個(gè)對(duì)象是否相等。

如下是jdkString類中自己重寫的equals方法,

public boolean equals(Object anObject) { // 如果兩個(gè)String類型的對(duì)象內(nèi)存地址相等直接返回trueif (this == anObject) { return true;} // 如下做的操作就是比較兩個(gè)字符串中的每一個(gè)char類型的數(shù)據(jù),如果都完全匹配,那么就是返回true,如果有一個(gè)不相同,直接返回false,并且兩個(gè)字符串的長(zhǎng)度要相等,如果不相同,那么肯定也就不可能值一樣了嘛if (anObject instanceof String) { String anotherString = (String)anObject; int n = value.length; if (n == anotherString.value.length) {char v1[] = value;char v2[] = anotherString.value;int i = 0;while (n-- != 0) { if (v1[i] != v2[i])return false; i++;}return true; }}return false; }

再看下String的hashcode方法:就是我們上面剛剛講過的那個(gè)方法

public int hashCode() {int h = hash;if (h == 0 && value.length > 0) { char val[] = value; for (int i = 0; i < value.length; i++) {h = 31 * h + val[i]; } hash = h;}return h; }

1:如果兩個(gè)String類型的對(duì)象內(nèi)存地址相等直接返回true

2:比較兩個(gè)字符串中的每一個(gè)char類型的數(shù)據(jù),如果都完全匹配,那么就是返回true,如果有一個(gè)不相同,直接返回false,并且兩個(gè)字符串的長(zhǎng)度要相等,如果不相同,那么肯定也就不可能值一樣了嘛

由此可以看出,equals方法是否返回true跟hashcode方法沒有半毛錢關(guān)系嘛。

接下來我們看下,我們自定義的對(duì)象,我創(chuàng)建一個(gè)User類,里面有屬性id和name

public class User { int id; String name; @Override public String toString() {return 'User{' +'id=' + id +', name=’' + name + ’’’ +’}’; }}

在沒有重寫hashcode方法和equals方法的情況下進(jìn)行比較:

User user1 = new User();User user2 = new User();System.out.println(user1.hashCode());System.out.println(user2.hashCode());System.out.println(user1.equals(user2));

詳解Java中的hashcode

解答:因?yàn)槲覀儧]有重寫,這兩個(gè)方法都是繼承自O(shè)bject類的,所以呢?比較的是內(nèi)存地址,因?yàn)槲覀兪峭ㄟ^new的方式去創(chuàng)建的兩個(gè)user對(duì)象,那么他們的內(nèi)存地址肯定是不相同的,所以直接返回false,而hashcode方法是java的底層語言c++來寫的,具體他內(nèi)部是怎么實(shí)現(xiàn)的,封裝了,我也就不得而知了,后面再了解,有的人說是跟內(nèi)存地址相關(guān),但是具體我沒有看到具體實(shí)現(xiàn),也不敢茍同,有的東西,需要自己不斷的去摸索,自己親自實(shí)踐,才是真的,不要相信別人說的。

好的,接下來我們重寫User類的hashcode方法:

public class User { int id; String name; @Override public String toString() {return 'User{' +'id=' + id +', name=’' + name + ’’’ +’}’; } @Override public int hashCode() {return Objects.hash(id, name); }}

詳解Java中的hashcode

可以看到的是,我們兩個(gè)User對(duì)象的hashcode方法返回的hash值是完全一致的,但是通過equals方法進(jìn)行比較,還是false,所以說,兩個(gè)對(duì)象的hashcode方法返回的hash值相同,equlas也一定返回true是完全不成立的,直接推翻。

接下來我們?cè)俅沃貙慹qulas方法,此時(shí)我們規(guī)定,只要兩個(gè)對(duì)象的id和name都相同,那么這兩個(gè)對(duì)象就是同一個(gè)對(duì)象。并且刪除掉剛剛我們重寫的hashcode方法。

public class User { int id; String name; public User(int i, String name) {this.id = id;this.name = name; } @Override public String toString() {return 'User{' +'id=' + id +', name=’' + name + ’’’ +’}’; } @Override public boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;User user = (User) o;return id == user.id &&name.equals(user.name); }}

詳解Java中的hashcode

通過運(yùn)行結(jié)果,我們可以看到,hashcode方法返回的hash值不一致,但是我們的equlas方法依舊返回的是true,因?yàn)檫@個(gè)equlas方法是我們重寫過了,在調(diào)用的時(shí)候,就不在去掉Object的equlas方法,進(jìn)行比較內(nèi)存地址,而是按照我們的重寫規(guī)則:如果兩個(gè)user對(duì)象的id和name相同,那么就是同一個(gè)對(duì)象,所以到這里,你是不是就具體的理解了hashcode方法個(gè)equlas之間的關(guān)系呢?

如果還是不明白,那再看一次,我們現(xiàn)在把User類的equlas方法和hashcode方法都寫上,但是呢?我會(huì)創(chuàng)建兩i不同的User對(duì)象(也就是id和name都不一樣)。

public class User { int id; String name; public User(int i, String name) {this.id = id;this.name = name; } @Override public String toString() {return 'User{' +'id=' + id +', name=’' + name + ’’’ +’}’; } @Override public boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;User user = (User) o;return id == user.id &&name.equals(user.name); } @Override public int hashCode() {return Objects.hash(id, name); }}

詳解Java中的hashcode

由此可以看到,雖然hashcode方法返回的hash值相同,但是通過equlas方法進(jìn)行比較,返回的直接就是false。

這里我們說的有點(diǎn)??鋁斯??糾慈?粵接錁涂梢運(yùn)登宄?模??橋?yàn)绰手朋友矡解??躍投??鋁思婦洌?飧鑫惱率俏腋鋈說睦斫猓?綣?脅徽?返南M?愣嗖慰際橐約骯僂??斜榷裕?暇寡奐??德錚?乙膊桓彝耆?Vの揖褪嵌緣摹?/p>

到此這篇關(guān)于詳解Java中的hashcode的文章就介紹到這了,更多相關(guān)Java hashcode內(nèi)容請(qǐng)搜索好吧啦網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持好吧啦網(wǎng)!

標(biāo)簽: Java
相關(guān)文章:
主站蜘蛛池模板: 学校用栓剂模,玻璃瓶轧盖钳,小型安瓿熔封机,实验室安瓿熔封机-长沙中亚制药设备有限公司 | 电渗析,废酸回收,双极膜-山东天维膜技术有限公司 | 商标转让-购买商标专业|放心的商标交易网-蜀易标商标网 | 无水硫酸铝,硫酸铝厂家-淄博双赢新材料科技有限公司 | 车载加油机品牌_ 柴油加油机厂家 | 熔体泵_熔体出料泵_高温熔体泵-郑州海科熔体泵有限公司 | Eiafans.com_环评爱好者 环评网|环评论坛|环评报告公示网|竣工环保验收公示网|环保验收报告公示网|环保自主验收公示|环评公示网|环保公示网|注册环评工程师|环境影响评价|环评师|规划环评|环评报告|环评考试网|环评论坛 - Powered by Discuz! | 工业废水处理|污水处理厂|废水治理设备工程技术公司-苏州瑞美迪 今日娱乐圈——影视剧集_八卦娱乐_明星八卦_最新娱乐八卦新闻 | 温控器生产厂家-提供温度开关/热保护器定制与批发-惠州市华恺威电子科技有限公司 | 软瓷_柔性面砖_软瓷砖_柔性石材_MCM软瓷厂家_湖北博悦佳软瓷 | 冷镦机-多工位冷镦机-高速冷镦机厂家-温州金诺机械设备制造有限公司 | 粘度计,数显粘度计,指针旋转粘度计| 硅胶布|电磁炉垫片|特氟龙胶带-江苏浩天复合材料有限公司 | 防渗膜厂家|养殖防渗膜|水产养殖防渗膜-泰安佳路通工程材料有限公司 | 巨野月嫂-家政公司-巨野县红墙安康母婴护理中心 | 化工ERP软件_化工新材料ERP系统_化工新材料MES软件_MES系统-广东顺景软件科技有限公司 | 流量检测仪-气密性检测装置-密封性试验仪-东莞市奥图自动化科技有限公司 | 打包箱房_集成房屋-山东佳一集成房屋有限公司 | 理化生实验室设备,吊装实验室设备,顶装实验室设备,实验室成套设备厂家,校园功能室设备,智慧书法教室方案 - 东莞市惠森教学设备有限公司 | 医疗仪器模块 健康一体机 多参数监护仪 智慧医疗仪器方案定制 血氧监护 心电监护 -朗锐慧康 | Akribis直线电机_直线模组_力矩电机_直线电机平台|雅科贝思Akribis-杭州摩森机电科技有限公司 | 防潮防水通风密闭门源头实力厂家 - 北京酷思帝克门窗 | 纸箱抗压机,拉力机,脂肪测定仪,定氮仪-山东德瑞克仪器有限公司 | nalgene洗瓶,nalgene量筒,nalgene窄口瓶,nalgene放水口大瓶,浙江省nalgene代理-杭州雷琪实验器材有限公司 | 定量包装秤,吨袋包装称,伸缩溜管,全自动包装秤,码垛机器人,无锡市邦尧机械工程有限公司 | RTO换向阀_VOC高温阀门_加热炉切断阀_双偏心软密封蝶阀_煤气蝶阀_提升阀-湖北霍科德阀门有限公司 | 自动钻孔机-全自动数控钻孔机生产厂家-多米(广东)智能装备有限公司 | 断桥铝破碎机_铝合金破碎机_废铁金属破碎机-河南鑫世昌机械制造有限公司 | POS机办理_个人POS机免费领取 - 银联POS机申请首页 | 耐热钢-耐磨钢-山东聚金合金钢铸造有限公司| 粘度计NDJ-5S,粘度计NDJ-8S,越平水分测定仪-上海右一仪器有限公司 | 氧化铝球_高铝球_氧化铝研磨球-淄博誉洁陶瓷新材料有限公司 | 桑茶-七彩贝壳桑叶茶 长寿茶| 小型单室真空包装机,食品单室真空包装机-百科 | 日本东丽膜_反渗透膜_RO膜价格_超滤膜_纳滤膜-北京东丽阳光官网 日本细胞免疫疗法_肿瘤免疫治疗_NK细胞疗法 - 免疫密码 | 真丝围巾|真丝丝巾|羊绒围巾|围巾品牌|浙江越缇围巾厂家定制 | 石磨面粉机|石磨面粉机械|石磨面粉机组|石磨面粉成套设备-河南成立粮油机械有限公司 | 卫生人才网-中国专业的医疗卫生医学人才网招聘网站! | Copeland/谷轮压缩机,谷轮半封闭压缩机,谷轮涡旋压缩机,型号规格,技术参数,尺寸图片,价格经销商 CTP磁天平|小电容测量仪|阴阳极极化_双液系沸点测定仪|dsj电渗实验装置-南京桑力电子设备厂 | 耐酸碱泵-自吸耐酸碱泵型号「品牌厂家」立式耐酸碱泵价格-昆山国宝过滤机有限公司首页 | 无线联网门锁|校园联网门锁|学校智能门锁|公租房智能门锁|保障房管理系统-KEENZY中科易安 |