日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

float foo=42e1为什么错_为什么重写了equals()也要重写hashCode()

發(fā)布時(shí)間:2023/12/9 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 float foo=42e1为什么错_为什么重写了equals()也要重写hashCode() 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

小Hub領(lǐng)讀:

雖然是很基礎(chǔ)的一篇文章,但是對(duì)于equals、hashcode兩個(gè)方法,相信很多人都與其中的規(guī)則不熟悉,來(lái)跟著小Hub花個(gè)8分鐘回顧一下!


作者:不學(xué)無(wú)數(shù)的程序員

https://my.oschina.net/u/4030990/blog/3134199

在?EffectiveJava中第九條規(guī)定在覆蓋?equals()方法時(shí)總要覆蓋?hashCode()方法。這是為什么呢?接下來(lái)我們就介紹一下這兩個(gè)方法。

Java中的?equals()方法和?hashCode()方法都是在?Object類中的方法,而在Java中所有的類都是?Obejct類的子類,所以Java中所有的方法都會(huì)有這兩個(gè)方法的默認(rèn)實(shí)現(xiàn)。

equals方法

Object類中的?equals()方法定義如下

public boolean equals(Object obj) {

return (this == obj);

}

我們發(fā)現(xiàn)在?equals()方法中就關(guān)鍵的?==,那么?==在Java中有什么含義呢,我們都知道在Java中分為基本數(shù)據(jù)類型和引用數(shù)據(jù)類型。那么?==在這兩個(gè)類型中作用是不一樣的。

  • 基本數(shù)據(jù)類型:比較的是?==兩邊值是否相等

  • 引用數(shù)據(jù)類型:比較的是?==兩邊內(nèi)存地址是否相等

基本數(shù)據(jù)類型包括:?byte,?short,?char,?int,?long,?float,?double,?boolean

而通過(guò)Java文檔中的?equals()方法描述,所有要實(shí)現(xiàn)自己的?equals()方法都要遵守下面幾個(gè)規(guī)則

  • 自反性:對(duì)于任何對(duì)象x,?x.equals(x)應(yīng)該返回?true

  • 對(duì)稱性:對(duì)于任何兩個(gè)對(duì)象x和y,如果?x.equals(y)返回?true,那么?y.equals(x)也應(yīng)該返回?true

  • 傳遞性:對(duì)于多個(gè)對(duì)象x,y,z,如果?x.equals(y)返回?true,?y.equals(z)返回?true,那么?y.equals(z)也應(yīng)該返回?true

  • 一致性:對(duì)于兩個(gè)非空對(duì)象x,y,在沒有修改此對(duì)象的前提下,多次調(diào)用返回的結(jié)果應(yīng)該相同

  • 對(duì)于任何非空的對(duì)象x,?x.equals(null)都應(yīng)該返回?false

hashCode方法

Object中的?hashCode()方法是一個(gè)本地方法,返回一個(gè)?int類型的哈希值。

public native int hashCode();

在?hashCode()方法中也有一些規(guī)約

  • 如果對(duì)象在使用?equals方法中進(jìn)行比較的參數(shù)沒有修改,那么多次調(diào)用一個(gè)對(duì)象的?hashCode()方法返回的哈希值應(yīng)該是相同的。

  • 如果兩個(gè)對(duì)象通過(guò)?equals方法比較是相等的,那么要求這兩個(gè)對(duì)象的?hashCode方法返回的值也應(yīng)該是相等的。

  • 如果兩個(gè)對(duì)象通過(guò)?equals方法比較是不同的,那么也不要求這兩個(gè)對(duì)象的?hashCode方法返回的值是相同的。但是我們應(yīng)該知道對(duì)于不同對(duì)象產(chǎn)生不同的哈希值對(duì)于哈希表(HashMap等等)能夠提高性能。

equals方法和hashCode方法會(huì)在哪用到

這兩個(gè)方法經(jīng)常出現(xiàn)在Java中的哪個(gè)類里面呢?如果看過(guò)?HashMap源碼的應(yīng)該了解這兩個(gè)方法經(jīng)常出現(xiàn)在?HashMap中。網(wǎng)上介紹?HashMap類的文章有很多了,這里就簡(jiǎn)單介紹一下?HashMap。

當(dāng)一個(gè)節(jié)點(diǎn)中的鏈表超過(guò)了8的時(shí)候就會(huì)變?yōu)榧t黑樹,以解決鏈表長(zhǎng)度過(guò)長(zhǎng)以后查詢速度慢的缺點(diǎn)。

HashMap是由數(shù)組和鏈表組成的高效存儲(chǔ)數(shù)據(jù)的結(jié)構(gòu)。那么是如何確定一個(gè)數(shù)據(jù)存儲(chǔ)在數(shù)組中的哪個(gè)位置呢?就是通過(guò)?hashCode方法進(jìn)行計(jì)算出存儲(chǔ)在哪個(gè)位置,還記得我們上面講?hashCode方法說(shuō)了有可能兩個(gè)不同對(duì)象的?hashCode方法返回的值相同,那么此時(shí)就會(huì)產(chǎn)生沖突,產(chǎn)生沖突的話就會(huì)調(diào)用?equals方法進(jìn)行比對(duì),如果不同,那么就將其加入鏈表尾部,如果相同就替換原數(shù)據(jù)。

計(jì)算位置當(dāng)然不是上面簡(jiǎn)單的一個(gè)?hashCode方法就計(jì)算出來(lái),中間還有一些其他的步驟,這里可以簡(jiǎn)單的認(rèn)為是?hashCode確定了位置。

什么時(shí)候去覆蓋這兩個(gè)方法呢?

如果你不將自定義的類定義為?HashMap的key值的話,那么我們重寫了?equals方法而沒有重寫?hashCode方法,編譯器不會(huì)報(bào)任何錯(cuò),在運(yùn)行時(shí)也不會(huì)拋任何異常。

如果你想將自定義的類定義為?HashMap的key值得話,那么如果重寫了?equals?方法那么就必須也重寫?hashCode方法。

接下來(lái)我們可以看一下我們使用自定義的類作為?HashMap的key,并且自定義的類不重寫?equals和?hashCode方法會(huì)發(fā)生什么。

自定義的類

@Builder

@NoArgsConstructor

@AllArgsConstructor

class CustomizedKey{

private Integer id;

private String name;

}

接下來(lái)我們看使用自定義的類作為key

public static void main(String[] args) {

Map<CustomizedKey, Integer> data = getData();

CustomizedKey key = CustomizedKey.builder().id(1).name("key").build();

Integer integer = data.get(key);

System.out.printf(String.valueOf(integer));

}

private static Map<CustomizedKey,Integer> getData(){

Map<CustomizedKey,Integer> customizedKeyIntegerMap = new HashMap<>();

CustomizedKey key = CustomizedKey.builder().id(1).name("key").build();

customizedKeyIntegerMap.put(key,10);

return customizedKeyIntegerMap;

}

我們可以看到程序最后打印的是一個(gè)?null值。原因正如上面我們說(shuō)的一樣。

  • hashCode:用來(lái)計(jì)算該對(duì)象放入數(shù)組中的哪個(gè)位置,因?yàn)槭莾蓚€(gè)都是new的對(duì)象,所以即使里面的值一樣,但是對(duì)象所處的地址卻不同,所以使用默認(rèn)的?hashCode也就不同,當(dāng)然在?hashMap中就不會(huì)認(rèn)為兩個(gè)是一個(gè)對(duì)象。

接下來(lái)我們就重寫一下這兩個(gè)方法。如果我們使用?IDEA的話,那么直接使用快捷鍵即可。

接下來(lái)我們看我們實(shí)現(xiàn)的兩個(gè)方法

@Builder

@NoArgsConstructor

@AllArgsConstructor

class CustomizedKey{

private Integer id;

private String name;

@Override

public boolean equals(Object o) {

if (this == o) return true;

if (o == null || getClass() != o.getClass()) return false;

CustomizedKey that = (CustomizedKey) o;

return Objects.equals(id, that.id) &&

Objects.equals(name, that.name);

}

@Override

public int hashCode() {

return Objects.hash(id, name);

}

}

然后我們?cè)俅芜\(yùn)行上面的程序發(fā)現(xiàn)輸出打印已經(jīng)變成了?10。

我們也能夠使用?Lombock提供的?@EqualsAndHashCode注解簡(jiǎn)化代碼

代碼地址:https://github.com/modouxiansheng/Doraemon


(完)

MarkerHub文章索引:

https://github.com/MarkerHub/JavaIndex

【推薦閱讀】

知乎問答:搞開發(fā)就怕加班還學(xué)不到東西?

很全很牛逼,看完這篇Elasticsearch實(shí)戰(zhàn),我覺得我可以寫個(gè)百度~

基于Jwt資源無(wú)狀態(tài)認(rèn)證權(quán)限管理系統(tǒng)bootshiro

別用Date了,Java8新特性之日期處理,現(xiàn)在學(xué)會(huì)也不遲!

eblog項(xiàng)目講解視頻上線啦,長(zhǎng)達(dá)17個(gè)小時(shí)!!

好文章!點(diǎn)個(gè)在看!

總結(jié)

以上是生活随笔為你收集整理的float foo=42e1为什么错_为什么重写了equals()也要重写hashCode()的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。