欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
Java 中的 ==, equals 與 hashCode 的區別與聯(lián)系

一、概述

1、概念

  • == : 該操作符生成的是一個(gè)boolean結果,它計算的是操作數的值之間的關(guān)系
  • equals : Object 的 實(shí)例方法,比較兩個(gè)對象的content是否相同
  • hashCode : Object 的 native方法 , 獲取對象的哈希值,用于確定該對象在哈希表中的索引位置,它實(shí)際上是一個(gè)int型整數

二、關(guān)系操作符 ==

1、操作數的值

  • 基本數據類(lèi)型變量

    在Java中有八種基本數據類(lèi)型:

      浮點(diǎn)型:float(4 byte), double(8 byte)

      整型:byte(1 byte), short(2 byte), int(4 byte) , long(8 byte)

      字符型: char(2 byte)

      布爾型: boolean(JVM規范沒(méi)有明確規定其所占的空間大小,僅規定其只能夠取字面值”true”和”false”)

      對于這八種基本數據類(lèi)型的變量,變量直接存儲的是“值”。因此,在使用關(guān)系操作符 == 來(lái)進(jìn)行比較時(shí),比較的就是“值”本身。要注意的是,浮點(diǎn)型和整型都是有符號類(lèi)型的(最高位僅用于表示正負,不參與計算【以 byte 為例,其范圍為 -2^7 ~ 2^7 - 1,-0即-128】),而char是無(wú)符號類(lèi)型的(所有位均參與計算,所以char類(lèi)型取值范圍為0~2^16-1)。


  • 引用類(lèi)型變量
    在Java中,引用類(lèi)型的變量存儲的并不是“值”本身,而是與其關(guān)聯(lián)的對象在內存中的地址。比如下面這行代碼,
    String str1;
  • 1

  這句話(huà)聲明了一個(gè)引用類(lèi)型的變量,此時(shí)它并沒(méi)有和任何對象關(guān)聯(lián)。
  而通過(guò) new 來(lái)產(chǎn)生一個(gè)對象,并將這個(gè)對象和str1進(jìn)行綁定:

str1= new String("hello");
  • 1

  那么 str1 就指向了這個(gè)對象,此時(shí)引用變量str1中存儲的是它指向的對象在內存中的存儲地址,并不是“值”本身,也就是說(shuō)并不是直接存儲的字符串”hello”。這里面的引用和 C/C++ 中的指針很類(lèi)似。


2、小結

 因此,對于關(guān)系操作符 ==:

  • 若操作數的類(lèi)型是基本數據類(lèi)型,則該關(guān)系操作符判斷的是左右兩邊操作數的是否相等
  • 若操作數的類(lèi)型是引用數據類(lèi)型,則該關(guān)系操作符判斷的是左右兩邊操作數的內存地址是否相同。也就是說(shuō),若此時(shí)返回true,則該操作符作用的一定是同一個(gè)對象。

三、equals方法

1、來(lái)源
  equals方法是基類(lèi)Object中的實(shí)例方法,因此對所有繼承于Object的類(lèi)都會(huì )有該方法。
  
  在 Object 中的聲明:

    public boolean equals(Object obj) {}
  • 1

2、equals方法的作用
 初衷 : 判斷兩個(gè)對象的 content 是否相同

 為了更直觀(guān)地理解equals方法的作用,我們先看Object類(lèi)中equals方法的實(shí)現。

  public boolean equals(Object obj) {    return (this == obj);  }
  • 1
  • 2
  • 3

  很顯然,在Object類(lèi)中,equals方法是用來(lái)比較兩個(gè)對象的引用是否相等,即是否指向同一個(gè)對象。

  但我們都知道,下面代碼輸出為 true:

public class Main {    public static void main(String[] args) {        String str1 = new String("hello");        String str2 = new String("hello");        System.out.println(str1.equals(str2));    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

原來(lái)是 String 類(lèi)重寫(xiě)了 equals 方法:

public boolean equals(Object anObject) {   // 方法簽名與 Object類(lèi) 中的一致    if (this == anObject) {     // 先判斷引用是否相同(是否為同一對象),        return true;    }    if (anObject instanceof String) {   // 再判斷類(lèi)型是否一致,        // 最后判斷內容是否一致.        String anotherString = (String)anObject;        int n = count;        if (n == anotherString.count) {        char v1[] = value;        char v2[] = anotherString.value;        int i = offset;        int j = anotherString.offset;        while (n-- != 0) {            if (v1[i++] != v2[j++])            return false;        }        return true;        }    }    return false;}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

即對于諸如“字符串比較時(shí)用的什么方法,內部實(shí)現如何?”之類(lèi)問(wèn)題的回答即為:

使用equals方法,內部實(shí)現分為三個(gè)步驟:

  • 比較引用是否相同(是否為同一對象),
  • 判斷類(lèi)型是否一致(是否為同一類(lèi)型),
  • 最后 比較內容是否一致

Java 中所有內置的類(lèi)的 equals 方法的實(shí)現步驟均是如此,特別是諸如 Integer,Double 等包裝器類(lèi)。


3、equals 重寫(xiě)原則

對象內容的比較才是設計equals()的真正目的,Java語(yǔ)言對equals()的要求如下,這些要求是重寫(xiě)該方法時(shí)必須遵循的:

  • 對稱(chēng)性: 如果x.equals(y)返回是“true”,那么y.equals(x)也應該返回是“true” ;

  • 自反性: x.equals(x)必須返回是“true” ;

  • 類(lèi)推性: 如果x.equals(y)返回是“true”,而且y.equals(z)返回是“true”,那么z.equals(x)也應該返回是“true” ;

  • 一致性: 如果x.equals(y)返回是“true”,只要x和y內容一直不變,不管你重復x.equals(y)多少次,返回都是“true” ;

  • 對稱(chēng)性: 如果x.equals(y)返回是“true”,那么y.equals(x)也應該返回是“true”。

  • 任何情況下,x.equals(null)【應使用關(guān)系比較符 ==】,永遠返回是“false”;x.equals(和x不同類(lèi)型的對象)永遠返回是“false”


4、小結
 因此,對于 equals 方法:

  • 本意比較兩個(gè)對象的 content 是否相同
  • 必要的時(shí)候,我們需要重寫(xiě)該方法,避免違背本意,且要遵循上述原則

四、hashCode 方法

1、hashCode 的來(lái)源
  hashCode 方法是基類(lèi)Object中的 實(shí)例native方法,因此對所有繼承于Object的類(lèi)都會(huì )有該方法。
  
  在 Object類(lèi) 中的聲明(native方法暗示這些方法是有實(shí)現體的,但并不提供實(shí)現體,因為其實(shí)現體是由非java語(yǔ)言在外面實(shí)現的):

     public native int hashCode();
  • 1

2、哈希相關(guān)概念
 我們首先來(lái)了解一下哈希表:

  • 概念 : Hash 就是把任意長(cháng)度的輸入(又叫做預映射, pre-image),通過(guò)散列算法,變換成固定長(cháng)度的輸出(int),該輸出就是散列值。這種轉換是一種 壓縮映射,也就是說(shuō),散列值的空間通常遠小于輸入的空間。不同的輸入可能會(huì )散列成相同的輸出,從而不可能從散列值來(lái)唯一的確定輸入值。簡(jiǎn)單的說(shuō),就是一種將任意長(cháng)度的消息壓縮到某一固定長(cháng)度的消息摘要的函數。

  • 應用–數據結構 : 數組的特點(diǎn)是:尋址容易,插入和刪除困難; 而鏈表的特點(diǎn)是:尋址困難,插入和刪除容易。那么我們能不能綜合兩者的特性,做出一種尋址容易,插入和刪除也容易的數據結構?答案是肯定的,這就是我們要提起的哈希表,哈希表有多種不同的實(shí)現方法,我接下來(lái)解釋的是最常用的一種方法——拉鏈法,我們可以理解為 “鏈表的數組”,如圖:

             


                            圖1 哈希表示例

     左邊很明顯是個(gè)數組,數組的每個(gè)成員是一個(gè)鏈表。該數據結構所容納的所有元素均包含一個(gè)指針,用于元素間的鏈接。我們根據元素的自身特征把元素分配到不同的鏈表中去,也是根據這些特征,找到正確的鏈表,再從鏈表中找出這個(gè)元素。其中,將根據元素特征計算元素數組下標的方法就是散列法。

  • 拉鏈法的適用范圍 : 快速查找,刪除的基本數據結構,通常需要總數據量可以放入內存。

  • 要點(diǎn) :
    hash函數選擇,針對字符串,整數,排列,具體相應的hash方法;
    碰撞處理,一種是open hashing,也稱(chēng)為拉鏈法,另一種就是closed hashing,也稱(chēng)開(kāi)地址法,opened addressing。

3、hashCode 簡(jiǎn)述
 在 Java 中,由 Object 類(lèi)定義的 hashCode 方法會(huì )針對不同的對象返回不同的整數。(這是通過(guò)將該對象的內部地址轉換成一個(gè)整數來(lái)實(shí)現的,但是 JavaTM 編程語(yǔ)言不需要這種實(shí)現技巧)。

 hashCode 的常規協(xié)定是:

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

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

  • 如果根據 equals(java.lang.Object) 方法,兩個(gè)對象不相等,那么對這兩個(gè)對象中的任一對象上調用 hashCode 方法 不要求 一定生成不同的整數結果。但是,程序員應該意識到,為不相等的對象生成不同整數結果可以提高哈希表的性能。
     
      要想進(jìn)一步了解 hashCode 的作用,我們必須先要了解Java中的容器,因為 HashCode 只是在需要用到哈希算法的數據結構中才有用,比如 HashSet, HashMap 和 Hashtable。

      Java中的集合(Collection)有三類(lèi),一類(lèi)是List,一類(lèi)是Queue,再有一類(lèi)就是Set。 前兩個(gè)集合內的元素是有序的,元素可以重復;最后一個(gè)集合內的元素無(wú)序,但元素不可重復。

      那么, 這里就有一個(gè)比較嚴重的問(wèn)題:要想保證元素不重復,可兩個(gè)元素是否重復應該依據什么來(lái)判斷呢? 這就是 Object.equals 方法了。但是,如果每增加一個(gè)元素就檢查一次,那么當元素很多時(shí),后添加到集合中的元素比較的次數就非常多了。 也就是說(shuō),如果集合中現在已經(jīng)有1000個(gè)元素,那么第1001個(gè)元素加入集合時(shí),它就要調用1000次equals方法。這顯然會(huì )大大降低效率。于是,Java采用了哈希表的原理。 這樣,我們對每個(gè)要存入集合的元素使用哈希算法算出一個(gè)值,然后根據該值計算出元素應該在數組的位置。所以,當集合要添加新的元素時(shí),可分為兩個(gè)步驟:
         

  • 先調用這個(gè)元素的 hashCode 方法,然后根據所得到的值計算出元素應該在數組的位置。如果這個(gè)位置上沒(méi)有元素,那么直接將它存儲在這個(gè)位置上;

  • 如果這個(gè)位置上已經(jīng)有元素了,那么調用它的equals方法與新元素進(jìn)行比較:相同的話(huà)就不存了,否則,將其存在這個(gè)位置對應的鏈表中(Java 中 HashSet, HashMap 和 Hashtable的實(shí)現總將元素放到鏈表的表頭)。


4、equals 與 hashCode

 前提: 談到hashCode就不得不說(shuō)equals方法,二者均是Object類(lèi)里的方法。由于Object類(lèi)是所有類(lèi)的基類(lèi),所以一切類(lèi)里都可以重寫(xiě)這兩個(gè)方法。

  • 原則 1 : 如果 x.equals(y) 返回 “true”,那么 x 和 y 的 hashCode() 必須相等 ;
  • 原則 2 : 如果 x.equals(y) 返回 “false”,那么 x 和 y 的 hashCode() 有可能相等,也有可能不等 ;
  • 原則 3 : 如果 x 和 y 的 hashCode() 不相等,那么 x.equals(y) 一定返回 “false” ;
  • 原則 4 : 一般來(lái)講,equals 這個(gè)方法是給用戶(hù)調用的,而 hashcode 方法一般用戶(hù)不會(huì )去調用 ;
  • 原則 5 : 當一個(gè)對象類(lèi)型作為集合對象的元素時(shí),那么這個(gè)對象應該擁有自己的equals()和hashCode()設計,而且要遵守前面所說(shuō)的幾個(gè)原則。

5、實(shí)現例證

 hashCode()在object類(lèi)中定義如下:

public native int hashCode();
  • 1

 說(shuō)明是一個(gè)本地方法,它的實(shí)現是根據本地機器相關(guān)的。

 String 類(lèi)是這樣重寫(xiě)它的:

public final class String    implements java.io.Serializable, Comparable<String>, CharSequence{    /** The value is used for character storage. */    private final char value[];     //成員變量1    /** The offset is the first index of the storage that is used. */    private final int offset;      //成員變量2    /** The count is the number of characters in the String. */    private final int count;       //成員變量3   /** Cache the hash code for the string */    private int hash; // Default to 0    //非成員變量    public int hashCode() {    int h = hash;        int len = count;         //用到成員變量3    if (h == 0 && len > 0) {        int off = offset;         //用到成員變量2        char val[] = value;       //用到成員變量1            for (int i = 0; i < len; i++) {                h = 31*h + val[off++];       //遞推公式            }            hash = h;        }        return h;    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

對程序的解釋?zhuān)?code>h = s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1],由此可以看出,對象的hash地址不一定是實(shí)際的內存地址。


五、小結

  • hashcode是系統用來(lái)快速檢索對象而使用
  • equals方法本意是用來(lái)判斷引用的對象是否一致
  • 重寫(xiě)equals方法和hashcode方法時(shí),equals方法中用到的成員變量也必定會(huì )在hashcode方法中用到,只不過(guò)前者作為比較項,后者作為生成摘要的信息項,本質(zhì)上所用到的數據是一樣的,從而保證二者的一致性
本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
新手必備Java快速掃盲指南
==、equals和hascode()區別
==和equals方法的區別是什么?hashCode方法的作用?
詳解 equals() 方法和 hashCode() 方法
==  和 equals
Java經(jīng)典面試題答案解析(1-80題)
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久