網頁

2014年1月8日 星期三

Effective Java實作hashCode()

hashCode()這個方法,也是定義在Object class中,這個是所有class的base class,因此所有的class也都繼承這個方法,預設是傳回這個物件儲存的記憶體位址編號,因為Mix覆寫了equals(),所以也應該一併覆寫hashCode(),Effective Java中推薦的實現方式如下:



  1. 初始化一個整數變數,給一個非零的整數值,如:int result=31。
  2. boolean,x?1:0。
  3. byte\char\short\int,計算(int)x。
  4. long值,計算(int)(x ^ (x >>> 32))。
  5. float值,計算Float.floatToIntBits(x)。
  6. double值,計算Double.doubleToLongBits(x),然後返回的結果是long,再用規則(4)去處理long,得到int。
  7. 物件應用,如果equals方法中採取遞迴呼叫的比較方式,那麼hashCode中同樣採取遞迴呼叫hashCode的方式。否則需要為這個域計算一個範式,比如當這個域的值為null的時候,那麼hashCode 值為0。
  8. 陣列,那麼需要為每個元素當做單獨的域來處理。如果你使用的是1.5及以上版本的JDK,那麼沒必要自己去重新遍歷一遍陣列,java.util.Arrays.hashCode方法包含了8種基本類型陣列和引用陣列的hashCode計算,演算法同上。





如果有使用ORM,如:Hibernate,有些field有可能會延遲加載,造成不正確,因此我們改成getter來取值。

 /*
  * (non-Javadoc)
  *
  * @see java.lang.Object#hashCode()
  */
 @Override
 public int hashCode() {
  final int prime = 31;
  int result = 1;
  //result = prime * result + (int) (id ^ (id >>> 32));
  result = prime * result + (int) (getId() ^ (getId() >>> 32));
  return result;
 }






覆寫hashCode()之後,Mix執行一次測試方法hashCodez(),來查看其結果。

 /**
  * HashCodez.
  */
 @Test
 public void hashCodez() {
  Role role = new RoleImpl();
  role.setId(1);
  //
  Role role2 = new RoleImpl();
  role2.setId(1);
  //
  boolean result = role.equals(role2);
  System.out.println(result);
  assertTrue(result);
  // 當role與role2相等, hashCode也需相等
  int hashCode = role.hashCode();
  int hashCode2 = role2.hashCode();
  System.out.println(hashCode + ", " + hashCode2);
  assertTrue(hashCode == hashCode2);
 }






測試成功了,滿足了當覆寫equals()時,也應該一併覆寫hashCode()。




console查看其結果。

true
32, 32






利用Apache Commons HashCodeBuilder來覆寫。

 /*
  * (non-Javadoc)
  *
  * @see java.lang.Object#hashCode()
  */
 @Override
 public int hashCode() {
  return new HashCodeBuilder().append(getId()).toHashCode();
 }





  1. Effective Java Item 9:當覆寫equals(),也應該一併覆寫hashCode()。



沒有留言:

張貼留言

Related Posts Plugin for WordPress, Blogger...