Java結合中的HashSet

quentain發表於2015-09-14

        HashSet是Set介面的典型實現,大多數時候使用Set集合時就是使用這個實現類。HashSet按Hash演算法來儲存集合中的元素,因此具有很好的存取和查詢效能。

HashSet具有以下特點:

(1)不能保證元素的排列順序,順序可能與新增順序不同,順序也可能發生變化。

(2)HashSet不是同步的,如果多個執行緒同時訪問一個HashSet,假設有兩個或者兩個以上執行緒同時修改了HashSet集合時,則必須通過程式碼來保證其同步。

(3)集合元素值可以是null。

         當向HashSet集合中存入一個元素時,HashSet會呼叫該物件的hashCode()方法來得到該物件的hashCode值,然後根據該hashCode值決定該物件在HashSet中的儲存位置。如果有兩個元素通過equals()方法比較返回true,但它們的hashCode()方法返回值不相等,HashSet將會把它們儲存在不同的位置,依然可以新增成功。

         也就是說,HashSet集合判斷兩個元素相等的標準是兩個物件通過equals()方法比較相等,並且兩個物件的hashCode()方法返回值也相等。

       下面程式分別提供了三個類A、B、C,它們分別重寫了equals()、hashCode()、兩個方法的一個或全部,通過此程式可以讓讀者看到HashSet判斷集合元素相同的標準。

 

package com.zhao.two;

import java.util.HashSet;

class A{
	  public boolean equals(Object obj){
		  return true;
	  }
}
class B{
	  public int hashCode(){
		  return 1;
	  }
}
class C{
	  public int hashCode(){
		  return 2;
	  }
	 public boolean equals(Object obj){
		 return true;
	 }
}
public class HashSetTest {
  public static void main(String[] args) {
	HashSet books=new HashSet();
	books.add(new A());
	books.add(new A());
	books.add(new B());
	books.add(new B());
	books.add(new C());
	books.add(new C());
	System.out.println(books);
  }
}

     上面程式中向books集合中分別新增了兩個A物件、兩個B物件和兩個C物件,其中C類重寫了equals()方法總是返回true,hashCode()方法總是返回2,這將導致HashSet把兩個C物件當成同一個物件。執行上面程式看到如下結果:

[com.zhao.two.B@1, com.zhao.two.B@1, com.zhao.two.C@2, com.zhao.two.A@2a139a55, com.zhao.two.A@15db9742]

      從上面程式可以看出,即使兩個A物件通過equals()方法比較返回true,但HashSet依然把它們當成;兩個物件;即使兩個B物件的hashCode()返回相同值都是1,但HashSet依然把它們當成兩個物件。

這裡有一個注意點:當把一個物件放入HashSet中時,如果需要寫該物件對應類的equals()方法,則也應該重寫其hashCode()方法。規則是:如果兩個物件通過equals()方法比較返回true,這兩個物件的hashCode值也應該相同。

    如果需要把某個類的物件儲存到HashSet集合中,重寫這個類的equals()方法和hashCode()方法時,應該儘量保證兩個物件通過equals()方法比較返回true,他們的hashCode()方法返回值也相等。

相關文章