精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

教妹學 Java :為什么重寫 Equals 時必須重寫 HashCode 方法

開發 后端
Java 是一門面向對象的編程語言,所有的類都會默認繼承自 Object 類,而 Object 的中文意思就是“對象”。

[[414302]]

 “二哥,我在讀《Effective Java》 的時候,第 11 條規約說重寫 equals 的時候必須要重寫 hashCode 方法,這是為什么呀?”三妹單刀直入地問。

“三妹啊,這個問題問得非常好,因為它也是面試中經常考的一個知識點。今天哥就帶你來梳理一下。”我說。

Java 是一門面向對象的編程語言,所有的類都會默認繼承自 Object 類,而 Object 的中文意思就是“對象”。

Object 類中有這么兩個方法:

  1. public native int hashCode(); 
  2.  
  3. public boolean equals(Object obj) { 
  4.         return (this == obj); 

1)hashCode 方法

這是一個本地方法,用來返回對象的哈希值(一個整數)。在 Java 程序執行期間,對同一個對象多次調用該方法必須返回相同的哈希值。

2)equals 方法

對于任何非空引用 x 和 y,當且僅當 x 和 y 引用的是同一個對象時,equals 方法才返回 true。

“二哥,看起來兩個方法之間沒有任何關聯啊?”三妹質疑道。

“單從這兩段解釋上來看,的確是這樣的。”我解釋道,“但兩個方法的 doc 文檔中還有這樣兩條信息。”

第一,如果兩個對象調用 equals 方法返回的結果為 true,那么兩個對象調用 hashCode 方法返回的結果也必然相同——來自 hashCode 方法的 doc 文檔。

第二,每當重寫 equals 方法時,hashCode 方法也需要重寫,以便維護上一條規約。

“哦,這樣講的話,兩個方法確實關聯上了,但究竟是為什么呢?”三妹拋出了終極一問。

“hashCode 方法的作用是用來獲取哈希值,而該哈希值的作用是用來確定對象在哈希表中的索引位置。”我說。

哈希表的典型代表就是 HashMap,它存儲的是鍵值對,能根據鍵快速地檢索出對應的值。

  1. public V get(Object key) { 
  2.     HashMap.Node<K,V> e; 
  3.     return (e = getNode(hash(key), key)) == null ? null : e.value; 

這是 HashMap 的 get 方法,通過鍵來獲取值的方法。它會調用 getNode 方法:

  1. final HashMap.Node<K,V> getNode(int hash, Object key) { 
  2.     HashMap.Node<K,V>[] tab; HashMap.Node<K,V> first, e; int n; K k; 
  3.     if ((tab = table) != null && (n = tab.length) > 0 && 
  4.             (first = tab[(n - 1) & hash]) != null) { 
  5.         if (first.hash == hash && // always check first node 
  6.                 ((k = first.key) == key || (key != null && key.equals(k)))) 
  7.             return first
  8.         if ((e = first.next) != null) { 
  9.             if (first instanceof HashMap.TreeNode) 
  10.                 return ((HashMap.TreeNode<K,V>)first).getTreeNode(hash, key); 
  11.             do { 
  12.                 if (e.hash == hash && 
  13.                         ((k = e.key) == key || (key != null && key.equals(k)))) 
  14.                     return e; 
  15.             } while ((e = e.next) != null); 
  16.         } 
  17.     } 
  18.     return null

通常情況(沒有發生哈希沖突)下,first = tab[(n - 1) & hash] 就是鍵對應的值。按照時間復雜度來說的話,可表示為 O(1)。

如果發生哈希沖突,也就是 if ((e = first.next) != null) {} 子句中,可以看到如果節點不是紅黑樹的時候,會通過 do-while 循環語句判斷鍵是否 equals 返回對應值的。按照時間復雜度來說的話,可表示為 O(n)。

HashMap 是通過拉鏈法來解決哈希沖突的,也就是如果發生哈希沖突,同一個鍵的坑位會放好多個值,超過 8 個值后改為紅黑樹,為了提高查詢的效率。

顯然,從時間復雜度上來看的話 O(n) 比 O(1) 的性能要差,這也正是哈希表的價值所在。

“O(n) 和 O(1) 是什么呀?”三妹有些不解。

“這是時間復雜度的一種表示方法,隨后二哥專門給你講一下。簡單說一下 n 和 1 的意思,很顯然,n 和 1 都代表的是代碼執行的次數,假如數據規模為 n,n 就代表需要執行 n 次,1 就代表只需要執行一次。”我解釋道。

“三妹,你想一下,如果沒有哈希表,但又需要這樣一個數據結構,它里面存放的數據是不允許重復的,該怎么辦呢?”我問。

“要不使用 equals 方法進行逐個比較?”三妹有些不太確定。

“這種方法當然是可行的,就像 if ((e = first.next) != null) {} 子句中那樣,但如果數據量特別特別大,性能就會很差,最好的解決方案還是 HashMap。”

HashMap 本質上是通過數組實現的,當我們要從 HashMap 中獲取某個值時,實際上是要獲取數組中某個位置的元素,而位置是通過鍵來確定的。

  1. public V put(K key, V value) { 
  2.     return putVal(hash(key), key, value, falsetrue); 

這是 HashMap 的 put 方法,會將鍵值對放入到數組當中。它會調用 putVal 方法:

  1. final V putVal(int hash, K key, V value, boolean onlyIfAbsent, 
  2.                boolean evict) { 
  3.     HashMap.Node<K,V>[] tab; HashMap.Node<K,V> p; int n, i; 
  4.     if ((tab = table) == null || (n = tab.length) == 0) 
  5.         n = (tab = resize()).length; 
  6.     if ((p = tab[i = (n - 1) & hash]) == null
  7.         tab[i] = newNode(hash, key, value, null); 
  8.     else { 
  9.         // 拉鏈 
  10.     } 
  11.     return null

通常情況下,p = tab[i = (n - 1) & hash]) 就是鍵對應的值。而數組的索引 (n - 1) & hash 正是基于 hashCode 方法計算得到的。

  1. static final int hash(Object key) { 
  2.     int h; 
  3.     return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16); 

“那二哥,你好像還是沒有說為什么重寫 equals 方法的時候要重寫 hashCode 方法呀?”三妹忍不住了。

“來看下面這段代碼。”我說。

  1. public class Test { 
  2.     public static void main(String[] args) { 
  3.         Student s1 = new Student(18, "張三"); 
  4.         Map<Student, Integer> scores = new HashMap<>(); 
  5.         scores.put(s1, 98); 
  6.  
  7.         Student s2 = new Student(18, "張三"); 
  8.         System.out.println(scores.get(s2)); 
  9.     } 
  10.  class Student { 
  11.     private int age; 
  12.     private String name
  13.  
  14.      public Student(int age, String name) { 
  15.          this.age = age; 
  16.          this.name = name
  17.      } 
  18.  
  19.      @Override 
  20.      public boolean equals(Object o) { 
  21.          Student student = (Student) o; 
  22.          return age == student.age && 
  23.                  Objects.equals(name, student.name); 
  24.      } 
  25.  } 

我們重寫了 Student 類的 equals 方法,如果兩個學生的年紀和姓名相同,我們就認為是同一個學生,雖然很離譜,但我們就是這么草率。

在 main 方法中,18 歲的張三考試得了 98 分,很不錯的成績,我們把張三和他的成績放到 HashMap 中,然后準備取出:

  1. null 

“二哥,怎么輸出了 null,而不是預期當中的 98 呢?”三妹感到很不可思議。

“原因就在于重寫 equals 方法的時候沒有重寫 hashCode 方法。”我回答道,“equals 方法雖然認定名字和年紀相同就是同一個學生,但它們本質上是兩個對象,hashCode 并不相同。”

“那怎么重寫 hashCode 方法呢?”三妹問。

“可以直接調用 Objects 類的 hash 方法。”我回答。

  1. @Override 
  2. public int hashCode() { 
  3.     return Objects.hash(age, name); 

Objects 類的 hash 方法可以針對不同數量的參數生成新的哈希值,hash 方法調用的是 Arrays 類的 hashCode 方法,該方法源碼如下:

  1. public static int hashCode(Object a[]) { 
  2.  if (a == null
  3.      return 0; 
  4.  
  5.  int result = 1; 
  6.  
  7.  for (Object element : a) 
  8.      result = 31 * result + (element == null ? 0 : element.hashCode()); 
  9.  
  10.  return result; 

第一次循環:

  1. result = 31*1 + Integer(18).hashCode(); 

第二次循環:

  1. result = (31*1 + Integer(18).hashCode()) * 31 + String("張三").hashCode(); 

針對姓名年紀不同的對象,這樣計算后的哈希值很難很難很難重復的;針對姓名年紀相同的對象,哈希值保持一致。

再次執行 main 方法,結果如下所示:

  1. 98 

因為此時 s1 和 s2 對象的哈希值都為 776408。

“每當重寫 equals 方法時,hashCode 方法也需要重寫,原因就是為了保證:如果兩個對象調用 equals 方法返回的結果為 true,那么兩個對象調用 hashCode 方法返回的結果也必然相同。”我點題了。

“OK,get 了。”三妹開心地點了點頭,看得出來,今天學到了不少。

本文轉載自微信公眾號「沉默王二」,可以通過以下二維碼關注。轉載本文請聯系沉默王二公眾號。

 

責任編輯:武曉燕 來源: 沉默王二
相關推薦

2021-03-18 23:38:26

EqualsHashcode方法

2021-12-03 06:59:23

HashCodeEquals面試

2021-12-13 09:10:48

equalshashCodeJava

2019-08-16 10:10:07

hashcodeequalsJava

2023-10-08 07:13:19

equalshashCode哈希表

2021-05-10 11:38:07

Java數組IDEA

2021-06-06 20:56:48

Java內存 intern

2021-07-13 06:42:58

JavaEquals方法

2020-11-18 09:44:49

Java命名約定

2020-10-26 09:36:45

Java變量數據

2021-07-08 22:43:41

ThrowThrowsJava

2021-07-26 17:22:02

Java

2021-07-03 17:53:52

Java異常處理機制

2021-06-11 18:08:00

Java字符串拼接

2021-12-30 19:36:48

GoDubboJava

2022-01-07 14:05:33

DubboGoJava

2020-10-29 10:28:31

Java數據類型

2018-05-07 15:59:39

代碼程序員重寫

2015-07-28 10:28:54

程序員代碼

2015-07-27 15:27:11

程序員重寫代碼
點贊
收藏

51CTO技術棧公眾號

3atv在线一区二区三区| 中文乱码免费一区二区| 97久久久免费福利网址| 少妇久久久久久久久久| 偷拍自拍亚洲| 午夜视频在线观看一区二区 | 中文字幕第一页在线播放| 日韩激情图片| 亚洲成人教育av| 三年中国国语在线播放免费| h视频在线免费观看| 99久久精品免费看国产免费软件| 国产精品精品视频| 久久久无码精品亚洲国产| 国产欧美日韩精品一区二区免费 | 人人妻人人澡人人爽人人欧美一区 | 亚洲日韩欧美视频一区| 99精品视频免费版的特色功能| 男人av在线播放| 亚洲欧美另类小说视频| 日韩电影免费观看在| www.国产精品视频| 人人精品人人爱| 91成人在线播放| 激情四射综合网| 97视频热人人精品免费| 日韩精品免费视频| 手机看片一级片| 午夜影院在线观看国产主播| 亚洲人成精品久久久久| 亚洲国产精品www| 日韩美女一级视频| 成人性生交大合| 亚洲jizzjizz日本少妇| 依依成人在线视频| 久久精品五月| 91精品国产乱码久久久久久蜜臀| 男的操女的网站| 日韩电影一区| 一区二区国产精品视频| 国产ts丝袜人妖系列视频| 一区二区日韩| 日韩欧美一级在线播放| 亚洲 国产 图片| 欧美少妇激情| 欧美美女一区二区| 九色porny自拍| 欧美粗大gay| 日本二三区不卡| 成人午夜激情av| 国产精品美女午夜爽爽| 欧美在线观看18| 网站一区二区三区| 国产精品传媒麻豆hd| 欧美视频一区在线观看| 中文字幕第80页| 国精产品一区一区三区四川| 欧美在线短视频| 五月婷婷深爱五月| 激情久久一区二区| 欧美色偷偷大香| 亚洲娇小娇小娇小| av一级久久| 91精品在线免费观看| xxx中文字幕| y111111国产精品久久久| 亚洲第一区中文字幕| 99re这里只有| 久久91麻豆精品一区| 中文字幕九色91在线| 日本不卡一区视频| 欧美96在线丨欧| 国产一区二区精品调教| 中文欧美字幕免费| 91社在线播放| 天堂av在线电影| 亚洲1区2区3区4区| 精品久久久久久无码国产| 97精品国产综合久久久动漫日韩 | 99久久精品国产一区色| 国产成人精品综合在线观看 | 无码精品视频一区二区三区 | 久久精品72免费观看| 91理论片午午论夜理片久久| 黄色片一区二区三区| 久久综合成人精品亚洲另类欧美 | 亚洲国产精品va| 最近中文字幕在线mv视频在线| 精品视频久久| 欧美乱妇40p| av大全在线观看| 久久www免费人成看片高清| 国产精品一区二区av| 男人天堂网在线| 亚洲视频在线观看一区| 国产白丝袜美女久久久久| 高清电影一区| 精品国产制服丝袜高跟| 久久久视频6r| 欧美特黄a级高清免费大片a级| 欧美日韩成人在线播放| 天天干天天插天天射| 国产传媒一区在线| 日韩色妇久久av| 久草成色在线| 欧美日韩二区三区| 国产精品狼人色视频一区| 国产精品suv一区| 韩国av一区二区三区在线观看| 精品国产福利| av网站在线免费| 一本大道久久a久久综合婷婷| 天堂中文av在线| 亚洲精品动态| 久久人人看视频| 国产剧情精品在线| 久久精品网站免费观看| 福利视频一区二区三区四区| 久久久久黄色| 亚洲欧洲在线播放| 日韩视频免费观看高清| 国产美女在线精品| 一区二区日本伦理| 搜成人激情视频| 精品无人国产偷自产在线| 欧美极品aaaaabbbbb| 美女视频一区在线观看| 欧美日韩免费精品| 婷婷电影在线观看| 日韩h在线观看| 国产精品第一页在线观看| 激情综合色播五月| 亚洲天堂电影网| 视频精品导航| 中文字幕国产日韩| 久久久久精彩视频| 久久久午夜电影| 岳毛多又紧做起爽| 色综合久久中文| 91超碰caoporn97人人| 熟妇人妻av无码一区二区三区| 亚洲自拍与偷拍| 亚洲欧洲日韩综合| 亚洲欧美伊人| dy888夜精品国产专区| 日日夜夜天天综合入口| 日韩一区二区三区视频| 激情五月婷婷在线| 成人免费观看av| 天堂…中文在线最新版在线| 国产一区二区三区亚洲| 97国产成人精品视频| 亚洲 欧美 自拍偷拍| 狠狠色香婷婷久久亚洲精品| 日韩片在线观看| 午夜一区在线| 日本一区二区三区在线视频 | 亚洲一区成人| 欧美国产二区| 国产综合色在线观看| 色琪琪综合男人的天堂aⅴ视频| 在线观看不卡的av| 亚洲品质自拍视频| 无码国产精品一区二区免费式直播 | 成人免费三级在线| 99热在线这里只有精品| 久久超碰99| 国产精品视频自拍| av网站免费在线观看| 亚洲成人久久一区| 天堂а√在线中文在线新版| 国产日产欧美精品一区二区三区| 韩国视频一区二区三区| 91精品国产91久久久久久密臀| 亚洲精品欧美日韩| 国产精选在线| 这里只有精品在线播放| 国产女主播福利| 亚洲国产cao| 法国空姐电影在线观看| 极品少妇xxxx偷拍精品少妇| 久久国产午夜精品理论片最新版本| 色婷婷av一区二区三区丝袜美腿| 国产精品视频在线观看| 好看的中文字幕在线播放| 亚洲欧美在线看| 国产精品无码在线播放| 精品久久久久久久久久国产| www成人啪啪18软件| 国产99一区视频免费| 成年人免费大片| 欧美二区不卡| 日本三级中国三级99人妇网站| 麻豆精品国产| 国产成人午夜视频网址| 丝袜在线视频| 中文在线资源观看视频网站免费不卡| 亚洲毛片在线播放| 欧美午夜精品免费| 日韩欧美不卡视频| 亚洲色图一区二区| 久久久亚洲av波多野结衣| 久久97超碰色| 国产成人黄色片| 91超碰国产精品| 日韩不卡av| 三级小说欧洲区亚洲区| 亚洲xxxx3d| 国产极品久久久久久久久波多结野| 久久99热精品这里久久精品| 91亚洲精选| 亚洲精品自拍偷拍| 亚洲精品一区二区三区四区| 欧美撒尿777hd撒尿| 西西44rtwww国产精品| 亚洲永久精品大片| 免费观看特级毛片| 国产人妖乱国产精品人妖| 老司机午夜免费福利| 国产麻豆精品一区二区| 最新天堂中文在线| 老司机精品视频网站| 国产人妻777人伦精品hd| 女生裸体视频一区二区三区| 一区二区三区在线视频111| 伊人久久大香线蕉无限次| 国内一区在线| 久久99精品国产自在现线| 99re视频在线观看| 成人免费91| 国产一区二区丝袜高跟鞋图片| 亚洲伦乱视频| 日韩免费观看在线观看| 日韩脚交footjobhd| 久久久久久有精品国产| 精精国产xxxx视频在线中文版| 久久亚洲精品视频| 蜜桃视频在线观看www社区| 色哟哟入口国产精品| av色图一区| 在线观看欧美成人| 99视频在线观看地址| 国产一区二区精品丝袜| 黄色在线观看网| 国产午夜精品一区二区三区 | 亚洲欧美日本在线| 日本在线一级片| 亚洲黄色小说网站| 免费在线观看国产精品| 亚洲a一区二区| 久草精品视频在线观看| 香蕉乱码成人久久天堂爱免费| 国产乡下妇女做爰| 欧美视频在线观看 亚洲欧| 天天操夜夜操视频| 欧美自拍偷拍一区| 亚洲一级视频在线观看| 69久久夜色精品国产69蝌蚪网| 99国产精品欲| 亚洲黄在线观看| 国产视频福利在线| 色午夜这里只有精品| 羞羞视频在线观看免费| 国色天香2019中文字幕在线观看| 乱馆动漫1~6集在线观看| 日本不卡高字幕在线2019| 日本成人福利| 成人免费看片网址| 日韩精品社区| 亚洲一二三区在线| 国精品一区二区| 黄色动漫网站入口| 日本va欧美va瓶| 性高潮久久久久久| 久久久久综合网| 久久精品在线观看视频| 亚洲一区二区三区中文字幕| 国产精品国产三级国产专区52| 在线观看av不卡| 午夜精品久久久久久久96蜜桃 | 黄色av免费播放| 亚洲激情在线播放| 亚洲不卡视频在线观看| 91.com视频| 午夜在线视频观看| 深夜福利日韩在线看| 国产理论电影在线| 国产精品wwwwww| 亚洲综合影院| 亚洲春色在线视频| 亚洲黄色影片| 国产三级国产精品国产专区50| 懂色av噜噜一区二区三区av | 亚洲综合图片区| 嫩草影院一区二区三区| 日韩你懂的在线播放| www黄在线观看| 海角国产乱辈乱精品视频| 国产精品成人国产| 久久精品人成| 欧美日韩在线大尺度| 成人性生生活性生交12| 波多野结衣视频一区| 蜜桃av.com| 一本久道久久综合中文字幕| 成人av无码一区二区三区| 中文字幕无线精品亚洲乱码一区| 成人在线黄色电影| 亚洲xxxx视频| 久久一本综合| 无码少妇一区二区三区芒果| 成人在线视频一区二区| 在线观看美女av| 在线视频国内自拍亚洲视频| 少妇荡乳情欲办公室456视频| 久久亚洲影音av资源网 | 欧美高清一级片在线| 九色在线观看| 91成人免费观看网站| 成人av综合网| 男人c女人视频| 国产精品自拍网站| 免费看特级毛片| 欧美理论电影在线| 成人免费在线电影| 国产成人激情视频| 欧美美乳视频| 99久久久无码国产精品6| 99久久久精品免费观看国产蜜| 久草免费在线视频观看| 欧美一区二区在线视频| 久久五月精品| 成人久久一区二区三区| 四虎成人精品永久免费av九九| 亚洲少妇第一页| 国产日韩在线不卡| 国产一级片免费视频| 亚洲欧美中文另类| 日本精品在线中文字幕| 日韩一本精品| 日本成人中文字幕| 在线观看免费黄色网址| 欧美三区在线视频| 日本中文在线观看| 国产日韩欧美在线视频观看| 99成人超碰| 亚洲欧美一区二区三区不卡| 亚洲欧美aⅴ...| 精品久久在线观看| 久久久久久91香蕉国产| 你懂的在线观看一区二区| 欧美性大战久久久久xxx| wwwwxxxxx欧美| 嫩草影院一区二区三区| 日韩视频永久免费观看| 国产专区精品| 欧美又粗又长又爽做受| 97超碰欧美中文字幕| 一级黄色av片| 久久婷婷国产麻豆91天堂| 超碰97久久| 国产又黄又大又粗视频| 国产欧美精品一区二区色综合| 一区二区三区在线免费观看视频| 久久精品亚洲精品| 88久久精品| aaa毛片在线观看| 中文字幕日韩精品一区| 性一交一乱一透一a级| 91爱视频在线| 欧美成人激情| 美女扒开腿免费视频| 欧洲精品在线观看| 快射av在线播放一区| 国产精品久久久久久久天堂第1集| 国产精品日本欧美一区二区三区| 国产亚洲精品熟女国产成人| 在线成人av网站| 国产在线精彩视频| 亚洲欧美日韩国产yyy| 国产高清久久久久| youjizz在线视频| 欧美成人免费大片| 亚洲天堂日韩在线| 永久av免费在线观看| 色综合久久综合网97色综合| 黄色片网站在线| 久久久福利视频| 狠狠狠色丁香婷婷综合激情 | 大吊一区二区三区| 精品美女被调教视频大全网站| 日韩视频网站在线观看| 女人色极品影院| 国产亚洲精品aa| 亚洲精品视频网| 国产剧情久久久久久| 亚洲另类黄色| 丝袜美腿小色网| 国产亚洲精品久久久久久牛牛| 亚洲综合网站|