當前位置:首頁 » 編程語言 » javahashcode

javahashcode

發布時間: 2022-04-24 07:21:20

java 的Object類的hashcode方法具體是怎麼實現的

一、在Object類中的定義為:
public native int hashCode();
是一個本地方法,返回的對象的地址值。
但是,同樣的思路,在String等封裝類中對此方法進行了重寫。方法調用得到一個計算公式得到的 int值。

二、在重寫任何類得hashcode方法時必須遵循以下幾點:
1、在Java應用的同一次執行過程中,同一對象被多次調用,則他們的hashcode值必然相同。而對於同一個應用的兩次不同的調用,它們的Hashcode值可以相同,也有可能不同。
2、對於兩個對象來說,如果他們的equals方法比較返回true,那麼這兩個對象的hashcode必然相同。這也解釋了為什麼String類中,如果兩個對象的equals方法相同,則他們的hashcode值一定相同。
3、對於兩個對象來說,如果使用equals方法返回為false,則他們的hashcode的值有可能相等也可能不等,(如果不同會提高性能,因為在集合中類判斷兩個對象是否相等,如果其hashcode不等就直接不用判斷equals方法了)
4、對於Object對象來說,不同的Object對象的hashcode是不同的,它們返回的是對象的地址,equals返回的也是對象的地址。所以在自己定義的類中如果要添加到集合對象中,最好是要重寫hashcode和equals方法,不然會自動繼承自Object類中的兩個方法根據對象地址來判斷。在重寫自己定義的類時,通常是在類中的根據某個值如name.hashcode();來進行判斷。

三、以HashSet 為例:
當我們使用HashSet時,hashCode()方法就會被得到調用,判斷已經存儲在集合中的對象的hashCode值是否與所增加。
對象的hashCode值一致,如果「不一致」則直接加進去(不用比較equals()提高效率),如果一致,則進行equals方法的比較,如果返回true,表明集合裡面已經有這個對象,不能添加進去了。如果是false表是集合裡面沒有這個對象,則可以加進去。所以在重寫hashcode()或者equals() 方法的任何一個方法時,必須重寫另外一個。
示例代碼:
/**
* People 手工重寫hashcode方法和equals方法 根據name來判斷 兩個對象是否相等。
*/
class People {
private String name;
public People(String name) {
this.name = name;
}
@Override
public boolean equals(Object obj) {
//如果是自己
if(this==obj){
return true ;
}
//如果是空
if(obj==null ){
return false;
}
//比較兩個People的名字是否相同
if(obj!=null && obj instanceof People){
if(((People)obj).name.equals(this.name))
return true ;
}
return false;
}
@Override
public int hashCode() {
// String的hashcode本來就是用來比較兩個字元是否相等
return name.hashCode();
}
}

Ⅱ java中hashcode方法

從一般角度來看,Equality 是不錯的,但是 hash code 更則具技巧性。如果我們在 hash code上多下點功夫,我們就能了解到 hash code 就是用在細微處去提升性能的。
大部分的數據結構使用equals去檢查是否他們包含一個元素。例如:
List<String> list = Arrays.asList("a", "b", "c");
boolean contains = list.contains("b");

這個變數 contains 是true。因為他們是相等的,雖然b的實例化(instance)雖然不完全一樣(再說一次,忽略String interning)。

將傳遞給 contains 的實例與每個元素進行比較很浪費時間。還好,整個這類數據結構使用了一種更高效的方法。它不會將請求的實例與每個元素比較,而是使用捷徑,找到可能與之相等的實例,然後只比較這幾項。
這個捷徑就是哈希碼——從對象計算出來的一個能代表該對象的整數值。與哈希碼相同的實例不必相等,但相等的實例一定有相同的哈希碼。(或者說應該有,我們稍後會對這個問題進行簡單討論)。這類的數據結構常常使用這種技術命名,在名稱中加入 Hash 以便識別,其中最具代表性的就是 HashMap。

Ⅲ java hashcode 有什麼用

在Java集合中有兩類,一類是List,一類是Set

他們之間的區別就在於List集合中的元素師有序的,且可以重復,而Set集合中元素是無序不可重復的。

對於List好處理,但是對於Set而言我們要如何來保證元素不重復呢?

通過迭代來equals()是否相等。數據量小還可以接受,當我們的數據量大的時候效率可想而知(當然我們可以利用演算法進行優化)。

比如我們向HashSet插入1000數據,難道我們真的要迭代1000次,調用1000次equals()方法嗎?hashCode提供了解決方案。

怎麼實現?我們先看hashCode的源碼(Object)。


publicnativeinthashCode();它是一個本地方法,它的實現與本地機器有關,這里我們暫且認為他返回的是對象存儲的物理位置(實際上不是,這里寫是便於理解)。

當我們向一個集合中添加某個元素,集合會首先調用hashCode方法,這樣就可以直接定位它所存儲的位置,

  • 若該處沒有其他元素,則直接保存。

  • 若該處已經有元素存在,就調用equals方法來匹配這兩個元素是否相同,

  • 相同則不存,不同則散列到其他位置。

  • 這樣處理,當我們存入大量元素時就可以大大減少調用equals()方法的次數,極大地提高了效率。

    所以hashCode在上面扮演的角色為尋域(尋找某個對象在集合中區域位置)。

    hashCode可以將集合分成若干個區域,每個對象都可以計算出他們的hash碼,可以將hash碼分組,每個分組對應著某個存儲區域,根據一個對象的hash碼就可以確定該對象所存儲區域,這樣就大大減少查詢匹配元素的數量,提高了查詢效率。

Ⅳ Java 中的hashcode到底是什麼啊怎樣判斷兩個元素或者對象的hashcode是否就相同了

問題一:貼一段java api里介紹hashCode的話。public int hashCode()

返回該對象的哈希碼值。支持此方法是為了提高哈希表(例如 java.util.Hashtable 提供的哈希表)的性能。

hashCode 的常規協定是:

在 Java 應用程序執行期間,在對同一對象多次調用 hashCode 方法時,必須一致地返回相同的整數,前提是將對象進行
equals 比較時所用的信息沒有被修改。從某一應用程序的一次執行到同一應用程序的另一次執行,該整數無需保持一致。

如果根據 equals(Object) 方法,兩個對象是相等的,那麼對這兩個對象中的每個對象調用
hashCode 方法都必須生成相同的整數結果。

如果根據 equals(java.lang.Object)
方法,兩個對象不相等,那麼對這兩個對象中的任一對象上調用 hashCode 方法不
要求一定生成不同的整數結果。但是,程序員應該意識到,為不相等的對象生成不同整數結果可以提高哈希表的性能。

實際上,由 Object 類定義的 hashCode
方法確實會針對不同的對象返回不同的整數。(這一般是通過將該對象的內部地址轉換成一個整數來實現的,但是 JavaTM 編程語言不需要這種實現技巧。)


問題2:判斷兩個元素對象的hashcode是否相同?一般來說a==b的話,他們的hashcode就相同了。hashcode也可以你自己定義

	a為該類非靜態變數
@Override
publicinthashCode(){
finalintprime=31;
intresult=1;
result=prime*result+a;
returnresult;
}

你可以讓hashCode()這個方法的值一直返回0或者返回1,只要你樂意。

問題3:沒啥關系,當然對hash表定址來說的話有關系。

Ⅳ JAVA中哈希碼具體是什麼

哈希其實只是一個概念,沒有什麼真實的指向。它的目的是保證數據均勻的分布到一定的范圍內。所以不同數據產生相同的哈希碼是完全可以的。
java中哈希一般是希望自己寫演算法的。隨便返回什麼都可以。如果什麼也不寫的話就會返回地址。如果自己寫,最簡單的做法是把所有欄位拼起一個長串做個hash值。

Ⅵ java中hashcode到底有什麼用,用於什麼情況,怎麼用

在Java集合中有兩類,一類是List,一類是Set

他們之間的區別就在於List集合中的元素師有序的,且可以重復,而Set集合中元素是無序不可重復的。


對於List好處理,但是對於Set而言我們要如何來保證元素不重復呢?


通過迭代來equals()是否相等。數據量小還可以接受,當我們的數據量大的時候效率可想而知(當然我們可以利用演算法進行優化)。


比如我們向HashSet插入1000數據,難道我們真的要迭代1000次,調用1000次equals()方法嗎?hashCode提供了解決方案。


怎麼實現?我們先看hashCode的源碼(Object)。

publicnativeinthashCode();
它是一個本地方法,它的實現與本地機器有關,這里我們暫且認為他返回的是對象存儲的物理位置(實際上不是,這里寫是便於理解)。

當我們向一個集合中添加某個元素,集合會首先調用hashCode方法,這樣就可以直接定位它所存儲的位置,

  1. 若該處沒有其他元素,則直接保存。

  2. 若該處已經有元素存在,就調用equals方法來匹配這兩個元素是否相同,

  3. 相同則不存,不同則散列到其他位置。


這樣處理,當我們存入大量元素時就可以大大減少調用equals()方法的次數,極大地提高了效率。


所以hashCode在上面扮演的角色為尋域(尋找某個對象在集合中區域位置)。


hashCode可以將集合分成若干個區域,每個對象都可以計算出他們的hash碼,可以將hash碼分組,每個分組對應著某個存儲區域,根據一個對象的hash碼就可以確定該對象所存儲區域,這樣就大大減少查詢匹配元素的數量,提高了查詢效率。

Ⅶ 如何正確實現Java中的hashCode方法

正確實現Java中的hashCode方法:
相等和哈希碼

相等是從一般的方面來講,哈希碼更加具有技術性。如果我們在理解方面存在困難,我們可以說,他們通過只是一個實現細節來提高了性能。
大多數的數據結構通過equals方法來判斷他們是否包含一個元素,例如:
List<String> list = Arrays.asList("a", "b", "c");
boolean contains = list.contains("b");

這個變數contains結果是true,因為,雖然」b」是不相同的實例(此外,忽略字元串駐留),但是他們是相等的。
通過比較實例的每個元素,然後將比較結果賦值給contains是比較浪費的,雖然整個類的數據結構進行了優化,能夠提升性能。
他們通過使用一種快捷的方式(減少潛在的實例相等)進行比較,從而代替通過比較實例所包含的每個元素。而快捷比較僅需要比較下面這些方面:
快捷方式比較即通過比較哈希值,它可以將一個實例用一個整數值來代替。哈希碼相同的實例不一定相等,但相等的實例一定具有有相同的哈希值。(或應該有,我們很快就會討論這個)這些數據結構經常通過這種這種技術來命名,可以通過Hash來識別他們的,其中,HashMap是其中最著名的代表。
它們通常是這樣這樣運作的
當添加一個元素,它的哈希碼是用來計算內部數組的索引(即所謂的桶)
如果是,不相等的元素有相同的哈希碼,他們最終在同一個桶上並且捆綁在一起,例如通過添加到列表。
當一個實例來進行contains操作時,它的哈希碼將用來計算桶值(索引值),只有當對應索引值上存在元素時,才會對實例進行比較。
因此equals,hashCode是定義在Object類中。
散列法的思想
如果hashCode作為快捷方式來確定相等,那麼只有一件事我們應該關心:相等的對象應該具有相同的哈希碼,這也是為什麼如果我們重寫了equals方法後,我們必須創建一個與之匹配的hashCode實現的原因!
否則相等的對象是可能不會有相同的哈希碼的,因為它們將調用的是Object's的默認實現。
HashCode 准則
引用自官方文檔
hashCode通用約定:
* 調用運行Java應用程序中的同一對象,hashCode方法必須始終返回相同的整數。這個整數不需要在不同的Java應用程序中保持一致。
* 根據equals(Object)的方法來比較,如果兩個對象是相等的,兩個對象調用hashCode方法必須產生相同的結果。
* 根據equals(Object)的方法是比較,如果兩個對象是不相等的,那麼兩個對象調用hashCode方法並不一定產生不同的整數的結果。但是,程序員應該意識到給不相等的對象產生不同的整數結果將有可能提高哈希表的性能。
第一點反映出了相等的一致性屬性,第二個就是我們上面提出的要求。第三個闡述了一個重要的細節,我們將在稍後討論。
HashCode實現
下面是非常簡單的Person.hashCode的實現
@Override
public int hashCode() {
return Objects.hash(firstName, lastName);
}

person』s是通過多個欄位結合來計算哈希碼的。都是通過Object的hash函數來計算。
選擇欄位
但哪些欄位是相關的嗎?需求將會幫助我們回答這個問題:如果相等的對象必須具有相同的哈希碼,那麼計算哈希碼就不應包括任何不用於相等檢查的欄位。(否則兩個對象只是這些欄位不同但是仍然有可能會相等,此時他們這兩個對象哈希碼卻會不相同。)
所以用於哈希組欄位應該相等時使用的欄位的子集。默認情況下都使用相同的欄位,但有一些細節需要考慮。
一致性
首先,有一致性的要求。它應該相當嚴格。雖然它允許如果一些欄位改變對應的哈希碼發生變化(對於可變的類是不可避免的),但是哈希數據結構並不是為這種場景准備的。
正如我們以上所見的哈希碼用於確定元素的桶。但如果hash-relevant欄位發生了改變,並不會重新計算哈希碼、也不會更新內部數組。
這意味著以後通過相等的對象,甚至同一實例進行查詢也會失敗,數據結構計算當前的哈希碼與之前存儲實例計算的哈希碼並不一致,並是錯誤的桶。
結論:最好不要使用可變欄位計算哈希碼!
性能
哈希碼最終計算的頻率與可能調用equals差不多,那麼這里將是影響性能的關鍵部分,因此考慮此部分性能也是非常有意義的。並且與equals相比,優化之後又更大的上升空間。
除非使用非常復雜的演算法或者涉及非常多的欄位,那麼計算哈希碼的運算成本是微不足道的、同樣也是不可避免的。但是也應該考慮是否需要包含所有的欄位來進行運算。集合需要特別警惕的對待。以Lists和sets為例,將會包含集合裡面的每一個元素來計算哈希碼。是否需要調用它們需要具體情況具體分析。
如果性能是至關重要的,使用Objects.hash因為需要為varargs創建一個數組也許並不是最好的選擇。但一般規則優化是適用的:不要過早地使用一個通用的散列碼演算法,也許需要放棄集合,只有優化分析顯示潛在的改進。
碰撞
總是關注性能,這個實現怎麼呢?
@Override
public int hashCode() {
return 0;
}

快是肯定的。相等的對象將具有相同的哈希碼。並且,沒有可變的欄位!
但是,我們之前說過的桶呢?!這種方式下所有的實例將會有相同的桶!這將會導致一個鏈表來包含所有的元素,這樣一來將會有非常差的性能。每次調用contains將會觸發對整個list線性掃描。
我們希望盡可能少的元素在同一個桶!一個演算法返回變化多端的哈希碼,即使對於非常相似的對象,是一個好的開始。
怎樣才能達到上面的效果部分取決於選取的欄位,我們在計算中包含更多的細節,越有可能獲取到不同的哈希碼。注意:這個與我們所說的性能是完全相反的。因此,有趣的是,使用過多或者過少的欄位都會導致糟糕的性能。
防止碰撞的另一部分是使用實際計算散列的演算法。
計算Hsah
最簡單的方法來計算一個欄位的哈希碼是通過直接調用hashCode,結合的話會自動完成。常見的演算法是首先在以任意數量的數值(通常是基本數據類型)反復進行相乘操作再與欄位哈希碼相加
int prime = 31;
int result = 1;
result = prime * result + ((firstName == null) ? 0 : firstName.hashCode());
result = prime * result + ((lastName == null) ? 0 : lastName.hashCode());
return result;

這可能導致溢出,但是不是特別有問題的,因為他們並沒有產生Java異常。
注意,即使是非常良好的的哈希演算法也可能因為輸入特定的模式的數據有導致頻繁碰撞。作為一個簡單的例子假設我們會計算點的散列通過增加他們的x和y坐標。當我們處理f(x) = -x線上的點時,線上的點都滿足:x + y == 0,將會有大量的碰撞。
但是:我們可以使用一個通用的演算法,只到分析表明並不正確,才需要對哈希演算法進行修改。
總結
我們了解到計算哈希碼就是壓縮相等的一個整數值:相等的對象必須有相同的哈希碼,而出於對性能的考慮:最好是盡可能少的不相等的對象共享相同的哈希碼。
這就意味著如果重寫了equals方法,那麼就必須重寫hashCode方法
當實現hashCode
使用與equals中使用的相同的欄位(或者equals中使用欄位的子集)
最好不要包含可變的欄位。
對集合不要考慮調用hashCode
如果沒有特殊的輸入特定的模式,盡量採用通用的哈希演算法
記住hashCode性能,所以除非分析表明必要性,否則不要浪費太多的精力。

Ⅷ java的hashCode方法的使用 希望詳細解釋!!!

java的hashCode方法
首先,想要明白hashCode的作用,你必須要先知道Java中的集合。總的來說,Java中的集合(Collection)有兩類,一類是List,再有一類是Set。你知道它們的區別嗎?前者集合內的元素是有序的,元素可以重復;後者元素無序,但元素不可重復。那麼這里就有一個比較嚴重的問題了:要想保證元素不重復,可兩個元素是否重復應該依據什麼來判斷呢?這就是Object.equals方法了。但是,如果每增加一個元素就檢查一次,那麼當元素很多時,後添加到集合中的元素比較的次數就非常多了。也就是說,如果集合中現在已經有1000個元素,那麼第1001個元素加入集合時,它就要調用1000次equals方法。這顯然會大大降低效率。 於是,Java採用了哈希表的原理。哈希演算法也稱為散列演算法,是將數據依特定演算法直接指定到一個地址上。如果詳細講解哈希演算法,那需要更多的文章篇幅,我在這里就不介紹了。初學者可以這樣理解,hashCode方法實際上返回的就是對象存儲的物理地址(實際上並不是真正的在內存的物理地址,不過可以這樣理解)。 這樣一來,當集合要添加新的元素時,先調用這個元素的hashCode方法,就一下子能定位到它應該放置的物理位置上。如果這個位置上沒有元素,它就可以直接存儲在這個位置上,不用再進行任何比較了;如果這個位置上已經有元素了,就調用它的equals方法與新元素進行比較,相同的話就不存了,不相同就散列其它的地址。所以這里存在一個沖突解決的問題。這樣一來實際調用equals方法的次數就大大降低了,幾乎只需要一兩次。 所以,
Java對於eqauls方法和hashCode方法是這樣規定的:

1、如果兩個對象相同,那麼它們的hashCode值一定要相同;

2、如果兩個對象的hashCode相同,它們並不一定相同 上面說的對象相同指的是用eqauls方法比較。 你當然可以不按要求去做了,但你會發現,相同的對象可以出現在Set集合中。同時,增加新元素的效率會大大下降。

如果你改寫了equal()方法,令兩個實際不是一個對象的兩個實例在邏輯上相等了,但是hashcode卻是不等。

所以要記得改寫hashcode。

不改寫會帶來什麼後果呢?當然,比如你在用hashmap,hashtable之類的設計hashcode的類的時候,就會出麻煩了。

至於如何改寫一個hashcode,這就有好有壞了,看各人的功底了。現在還有專門的人在研究優秀的hash演算法。

也就是說 List 是一個有序的、可重復的對象容器介面,Set是一個無序的、不可重復的對象容器介面 。後面都講了 Set 是如何實現不重復的 :為了避免多次重復的使用 equal 方法帶來的系統負擔 ,set 首先調用hashCode 方法來檢測 是否被佔用 如果被佔用 然後調用 equal 方法判斷被佔用的是否相同

Ⅸ java中「hashcode」什麼時候用怎麼用

有許多人學了很長時間的Java,但一直不明白hashCode方法的作用,
我來解釋一下吧。首先,想要明白hashCode的作用,你必須要先知道Java中的集合。
總的來說,Java中的集合(Collection)有兩類,一類是List,再有一類是Set。
你知道它們的區別嗎?前者集合內的元素是有序的,元素可以重復;後者元素無序,但元素不可重復。
那麼這里就有一個比較嚴重的問題了:要想保證元素不重復,可兩個元素是否重復應該依據什麼來判斷呢?
這就是Object.equals方法了。但是,如果每增加一個元素就檢查一次,那麼當元素很多時,後添加到集合中的元素比較的次數就非常多了。
也就是說,如果集合中現在已經有1000個元素,那麼第1001個元素加入集合時,它就要調用1000次equals方法。這顯然會大大降低效率。
於是,Java採用了哈希表的原理。哈希(Hash)實際上是個人名,由於他提出一哈希演算法的概念,所以就以他的名字命名了。
哈希演算法也稱為散列演算法,是將數據依特定演算法直接指定到一個地址上。如果詳細講解哈希演算法,那需要更多的文章篇幅,我在這里就不介紹了。
初學者可以這樣理解,hashCode方法實際上返回的就是對象存儲的物理地址(實際可能並不是)。
這樣一來,當集合要添加新的元素時,先調用這個元素的hashCode方法,就一下子能定位到它應該放置的物理位置上。
如果這個位置上沒有元素,它就可以直接存儲在這個位置上,不用再進行任何比較了;如果這個位置上已經有元素了,
就調用它的equals方法與新元素進行比較,相同的話就不存了,不相同就散列其它的地址。
所以這里存在一個沖突解決的問題。這樣一來實際調用equals方法的次數就大大降低了,幾乎只需要一兩次。
所以,Java對於eqauls方法和hashCode方法是這樣規定的:
1、如果兩個對象相同,那麼它們的hashCode值一定要相同;2、如果兩個對象的hashCode相同,它們並不一定相同 上面說的對象相同指的是用eqauls方法比較。
你當然可以不按要求去做了,但你會發現,相同的對象可以出現在Set集合中。同時,增加新元素的效率會大大下降。hashcode這個方法是用來鑒定2個對象是否相等的。 那你會說,不是還有equals這個方法嗎? 不錯,這2個方法都是用來判斷2個對象是否相等的。但是他們是有區別的。 一般來講,equals這個方法是給用戶調用的,如果你想判斷2個對象是否相等,你可以重寫equals方法,然後在代碼中調用,就可以判斷他們是否相等 了。簡單來講,equals方法主要是用來判斷從表面上看或者從內容上看,2個對象是不是相等。舉個例子,有個學生類,屬性只有姓名和性別,那麼我們可以 認為只要姓名和性別相等,那麼就說這2個對象是相等的。 hashcode方法一般用戶不會去調用,比如在hashmap中,由於key是不可以重復的,他在判斷key是不是重復的時候就判斷了hashcode 這個方法,而且也用到了equals方法。這里不可以重復是說equals和hashcode只要有一個不等就可以了!所以簡單來講,hashcode相 當於是一個對象的編碼,就好像文件中的md5,他和equals不同就在於他返回的是int型的,比較起來不直觀。我們一般在覆蓋equals的同時也要 覆蓋hashcode,讓他們的邏輯一致。舉個例子,還是剛剛的例子,如果姓名和性別相等就算2個對象相等的話,那麼hashcode的方法也要返回姓名 的hashcode值加上性別的hashcode值,這樣從邏輯上,他們就一致了。 要從物理上判斷2個對象是否相等,用==就可以了。

Ⅹ java 中 hashCode() 是干什麼的

重寫前,name1和name2兩個對象不相等,即name1.equals(name2)為false。重寫後name1和name2兩個對象在進行equals運算時得到的結果為true。而在集合HashSet中,它不允許存在重復的元素。所以在重寫前name1和name2兩個對象不相等時,HashSet的實例c中有兩個元素;重寫後name1和name2兩個對象相等了,存儲的元素就變為1了。

在重寫對象的equals方法時,jdk給我們的建議是同時重寫對象的hashCode值。這主要是為了保證一個對象只有唯一的hashCode值,兩個對象在進行equals運算時為false,那麼hashCode將也不相等。

熱點內容
羅技g502高級腳本 發布:2025-05-17 17:30:45 瀏覽:217
python解析post請求 發布:2025-05-17 17:27:19 瀏覽:696
社保測算密碼是什麼 發布:2025-05-17 17:25:09 瀏覽:157
phpini修改路徑 發布:2025-05-17 17:19:06 瀏覽:280
mac搭建php開發環境 發布:2025-05-17 17:18:22 瀏覽:782
佟大為關悅上超級訪問 發布:2025-05-17 17:09:50 瀏覽:310
閃迪存儲卡高速 發布:2025-05-17 17:09:14 瀏覽:470
ios文件加密插件 發布:2025-05-17 17:05:48 瀏覽:797
androidbutton自定義 發布:2025-05-17 16:58:34 瀏覽:169
android應用生命周期 發布:2025-05-17 16:53:16 瀏覽:779