亚洲精品久久久中文字幕-亚洲精品久久片久久-亚洲精品久久青草-亚洲精品久久婷婷爱久久婷婷-亚洲精品久久午夜香蕉

您的位置:首頁技術文章
文章詳情頁

詳解Java中的hashcode

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

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

這個說的有點官方,你就可以把它簡單的理解為一個key,就像是map的key值一樣,是不可重復的。

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

1.在散列表

2.map集合

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

三、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類型的方式進行一個相加,因為String類的底層就是通過char數組來實現的。

如:String str='ab'; 其實就是一個char數組 char[] str={’a’,’b’};

如:字符串 String star=“ab”;那么他對應的hash值就是:3105

怎么算出來的呢?

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

a對應的Ascall碼值為:97b對的Ascall碼值為:98那么經過如下代碼的循環相加

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

得出:97*31+98=3105;

我們再看: int h = hash;這一個代碼,為什么有時候調用hashcode方法返回的hash值是負數呢?

因為如果這個字符串很長?那么h的值就會超過int類型的最大值,有沒有想過,如果一個int類型的最大值,超過他的范圍之后會怎么樣呢?

我們先來看這樣一個簡單的代碼:

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

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

因為count一直加,最開始if成立,到后面的if不成立,再到后面if會再次成立,為什么會成立呢?因為count變為了負數。

???? 為什么?因為count一直無限制的加,由于是線性增長,計算速度是非常快的,所以,要不了多久,就會超出int類型的最大值。控制輸出的count變為了負數,所以呢此時的if條件又成立了。

詳解Java中的hashcode

首先我們來看下int的范圍 :int 為4個字節,一個字節為8位,一個int值是需要的存儲空間是32位,但是呢?這是一個有符號位的int,需要一個符號位來表示正數和負數,int值的范圍就是:-2^31 ~ 2^31 也就是:-2147483648 到2147483647

我們來看下int最大值對應的二進制位是對少?

詳解Java中的hashcode

全是1? 2147483647最大值不是一個正數么?難道第一位難道不是應該用0表示么?

此時這個0他是省略掉了沒寫的,由于二進制系統是通過補碼來保存數據的。第一位是符號位,0為正,1為負,當正的除了符號位全為1,再加1就進位了,符號位就會變成1,是負數,其他為0。所以說當int的最大值加一個1,就變為了,最小值

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

詳解Java中的hashcode

那么我們在反過來想,最小值減1呢?那是不是就是對對應的是我們int類型的最大值了呀?

認真仔細的看完這個,你就知道為什么hashcode方法調用的時候有時候是正數,有時候是負數了吧?所以說底層還是很有意思的,比如往后做大數據開發,那么肯定是需要深入理解這些數據類型的范圍,以及他的一個變化規則,否則有時候不知不覺的就犯錯了,你還不知道錯誤在那兒?嚴重的話就是會損失精度,導致結果和你預期的結果相差甚遠。就因為加了個1,就導致結果和預期結果相差十萬八千里。

這是String類的hashcode方法的一個具體實現過程。

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

首先呢?這個肯定是不對的。

因為這兩個方法都可以重寫,如果是自己的類,那么可以靈活重寫,如果是jdk自己的類,那就要看他到底有沒有重寫這兩個方法。

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

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

public boolean equals(Object anObject) { // 如果兩個String類型的對象內存地址相等直接返回trueif (this == anObject) { return true;} // 如下做的操作就是比較兩個字符串中的每一個char類型的數據,如果都完全匹配,那么就是返回true,如果有一個不相同,直接返回false,并且兩個字符串的長度要相等,如果不相同,那么肯定也就不可能值一樣了嘛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方法:就是我們上面剛剛講過的那個方法

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:如果兩個String類型的對象內存地址相等直接返回true

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

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

接下來我們看下,我們自定義的對象,我創建一個User類,里面有屬性id和name

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

在沒有重寫hashcode方法和equals方法的情況下進行比較:

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

解答:因為我們沒有重寫,這兩個方法都是繼承自Object類的,所以呢?比較的是內存地址,因為我們是通過new的方式去創建的兩個user對象,那么他們的內存地址肯定是不相同的,所以直接返回false,而hashcode方法是java的底層語言c++來寫的,具體他內部是怎么實現的,封裝了,我也就不得而知了,后面再了解,有的人說是跟內存地址相關,但是具體我沒有看到具體實現,也不敢茍同,有的東西,需要自己不斷的去摸索,自己親自實踐,才是真的,不要相信別人說的。

好的,接下來我們重寫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

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

接下來我們再次重寫equlas方法,此時我們規定,只要兩個對象的id和name都相同,那么這兩個對象就是同一個對象。并且刪除掉剛剛我們重寫的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

通過運行結果,我們可以看到,hashcode方法返回的hash值不一致,但是我們的equlas方法依舊返回的是true,因為這個equlas方法是我們重寫過了,在調用的時候,就不在去掉Object的equlas方法,進行比較內存地址,而是按照我們的重寫規則:如果兩個user對象的id和name相同,那么就是同一個對象,所以到這里,你是不是就具體的理解了hashcode方法個equlas之間的關系呢?

如果還是不明白,那再看一次,我們現在把User類的equlas方法和hashcode方法都寫上,但是呢?我會創建兩i不同的User對象(也就是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方法進行比較,返回的直接就是false。

這里我們說的有點??鋁斯??糾慈?粵接錁涂梢運登宄?模??橋灤率峙笥巡煥斫猓??躍投??鋁思婦洌?飧鑫惱率俏腋鋈說睦斫猓?綣?脅徽?返南M?愣嗖慰際橐約骯僂??斜榷裕?暇寡奐??德錚?乙膊桓彝耆?Vの揖褪嵌緣摹?/p>

到此這篇關于詳解Java中的hashcode的文章就介紹到這了,更多相關Java hashcode內容請搜索好吧啦網以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持好吧啦網!

標簽: Java
相關文章:
主站蜘蛛池模板: 国产亚洲精品自在久久77 | 99re热这里只有精品18 | 国产乱人视频免费播放 | 成人一区二区免费中文字幕 | 国产成人精品本亚洲 | 国产一区二区三区免费视频 | 成年女人毛片免费视频 | 国产又色又爽又黄的网站在线一级 | 亚洲精品黄色 | 国产伦精品一区二区三区免费迷 | 精品国精品自拍自在线 | 在线播放国产麻豆 | 97福利社 | 久热在线视频 | 青青综合 | 黄色大片在线 | 国产女女视屏免费 | 日本免费黄色片 | 在线不卡一区二区三区日韩 | 又粗又大又爽 真人一级毛片 | 国产最新自拍视频 | 一级毛片美国一级j毛片不卡 | 在线国产不卡 | 精品无人区一区二区三区 | 中国毛片视频 | aa级毛片| 国内自拍网 | 美女国产福利视频 | 国产高清小视频 | 国产成人免费高清激情视频 | 国产女人在线 | 亚洲精品第一国产综合高清 | 亚洲国产精品线播放 | 国语自产免费精品视频一区二区 | 精品玖玖玖视频在线观看 | 做受又硬又粗又免费视频 | 天天操夜夜草 | 国产成人亚洲影视在线 | 国产乡下三级全黄三级带 | 国产高清视频在线播放www色 | 中文字幕无线码一区二区三区 |