利用Commons Lang庫改寫equals與hashCode方法

來源:互聯網
上載者:User
關於如何改變
Java類中的equals與hashCode方法,Effective Java一書中提供了一個行之有效方法。改寫equals方法的步驟為:
  1. 使
    用==操作符檢查“實參是否為指向對象的一個引用”。
  2. 使用instanceof操作符檢查“實參是否為正確的類型”。

  3. 實參轉換到正確的類型。
  4. 對於該類中每一個“關鍵”域,檢查實參中的域與當前對象中對應的域值是否匹配。

其中最後一步書中的描述為:

  • 對於既不是float也不是double類型的簡單類型域,可以使用==操作符進行比較;

  • 於對象參考網域,可以遞迴地調用equals方法;
  • 對於float域,先使用Float.floatToIntBits轉換成int類型
    的值,然後使用==操作符比較int類型的值;
  • 對於double域,先使用Double.doubleToLongBits轉換成
    long類型的值,然後使用==操作符比較long類型的值;
  • 對於數組域,把以上這些指導原則應用到每個元素上。
有些對象參考網域包含null是合法的,所以為了避免可能導致NullPointerException
異常,使用下面的習慣用法來比較這樣的域:
(field == o.field || (field != null && field.equals(o.field))
改寫equals時總是要改寫hashCode,改寫hashCode方法的步驟為:
  1. 把某個非零常數值比如說17,
    儲存在一個叫result的int類型的變數中。
  2. 對於對象中每一個關鍵域f(指equals方法中考慮的每一個域),完成以下步驟:
    1. 為該域計算int類型的散列碼c:
      1. 如果該域是boolean類型,則計算(f ? 0 : 1)。
      2. 如果該域是byte、
        char、short或者int類型,則計算(int)f。
      3. 如果該域是long類型,則計算(int)(f ^ (f
        >>> 32))。
      4. 如果該域是float類型,則計算Float.floatToIntBits(f)。

      5. 果該域是double類型,則計算Double.doubleToLongBits(f)得到一個long類型的值,然後按照步驟2.1.3,對該
        long型值計算散列值。
      6. 如果該域是一個對象引用,並且該類的equals方法通過遞迴調用equals的方式來比較這個域,則同樣對
        這個域遞迴調用hashCode。如果這個域的值為null,則返回0。
      7. 如果該域是一個數組,則把每一個元素當做單獨的域來處理。
    2. 按照下面的公式,把步驟a中計算得到的散列碼c組合到result中:result = 37 * result + c
  3. 返回result。

上述方案中關於“關鍵”域的計算過程是比較複雜的,看一看下面這個簡單類Point實現的equals與
hashCode方法:

public class Point {<br /> private final int x;<br /> private final int y;<br /> public Point(int x, int y) {<br /> this.x = x;<br /> this.y = y;<br /> }<br /> public int getX() {<br /> return x;<br /> }<br /> public int getY() {<br /> return y;<br /> }<br /> @Override<br /> public boolean equals(Object other) {<br /> // step 1<br /> if (other == this) {<br /> return true;<br /> }<br /> // step 2<br /> if (!(other instanceof Point)) {<br /> return false;<br /> }</p><p> // step 3<br /> Point that = (Point) other;<br /> // step 4<br /> boolean result =<br /> (this.getX() == that.getX()) &&<br /> (this.getY() == that.getY());<br /> return result;<br /> }<br /> @Override<br /> public int hashCode() {<br /> // step 1<br /> int result = 17;<br /> // step 2<br /> result = 37 * result + getX();<br /> result = 37 * result + getY();<br /> // step 3<br /> return result;<br /> }<br />}如果“關鍵”域數量較多,實現上難免出現錯誤。Commons
Lang庫為我們提供了兩個工具類用於簡化equals方法的第4步及hashCode方法的第2步,它們分別為EqualsBuilder與HashCodeBuilder類。如上例的Commons Lang庫版本:import org.apache.commons.lang.builder.EqualsBuilder;<br />import org.apache.commons.lang.builder.HashCodeBuilder;<br />public class Point {<br /> private final int x;<br /> private final int y;<br /> public Point(int x, int y) {<br /> this.x = x;<br /> this.y = y;<br /> }<br /> public int getX() {<br /> return x;<br /> }<br /> public int getY() {<br /> return y;<br /> }<br /> @Override<br /> public boolean equals(Object other) {<br /> // step 1<br /> if (other == this) {<br /> return true;<br /> }<br /> // step 2<br /> if (!(other instanceof Point)) {<br /> return false;<br /> }</p><p> // step 3<br /> Point that = (Point) other;<br /> // step 4<br /> return new EqualsBuilder()<br /> .append(this.getX(), that.getX())<br /> .append(this.getY(), that.getY())<br /> .isEquals();<br /> }<br /> @Override<br /> public int hashCode() {<br /> return new HashCodeBuilder(17, 37)<br /> .append(this.getX())<br /> .append(this.getY())<br /> .toHashCode();<br /> }<br />}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.