——- android培訓、java培訓、期待與您交流! ———-
問題:hashCode()在對象比較時很常用,那麼它的作用究竟是什麼?
1)利用哈希算法,提高了查找效率。
2)hashCode必須在哈希集合中才有用。
3)防止內存泄露。對象不用了,但是它沒有被釋放掉,一直佔用內存。
看下面實例1:
定義已知類ReflectPoint
class ReflectPoint
{
private int x;
public int y;
public String str1 = "ball";
public String str2 = "basketball";
public String str3 = "all";
public ReflectPoint(int x,int y)
{
super();
this.x = x;
this.y = y;
}
public String toString()
{
return str1+"......"+str2+"......"+str3+"......";
}
}
public class ReflectTest2
{
public static void main(String args[])
{
Collection collections = new ArrayList();
ReflectPoint pt1 = new ReflectPoint(3,3);
ReflectPoint pt2 = new ReflectPoint(5,5);
ReflectPoint pt3 = new ReflectPoint(3,3);
collections.add(pt1);
collections.add(pt2);
collections.add(pt3);
collections.add(pt1);
System.out.println(collections.size());//打印結果爲4
}
}
該上述代碼ArrayList爲HashSet看結果又如何?
示例2:
public class ReflectTest2
{
public static void main(String args[])
{
Collection collections = new ArrayList();
ReflectPoint pt1 = new ReflectPoint(3,3);
ReflectPoint pt2 = new ReflectPoint(5,5);
ReflectPoint pt3 = new ReflectPoint(3,3);
collections.add(pt1);
collections.add(pt2);
collections.add(pt3);
collections.add(pt1);
System.out.println(collections.size());//打印結果爲3
}
}
這是因爲ArrayList可以存放相同對象,而HashSet不可存放相同對象。
但是當ReflectPoint覆寫hashCode()和equals()方法後,看結果又如何?
示例3:
定義已知類ReflectPoint
class ReflectPoint
{
private int x;
public int y;
public String str1 = "ball";
public String str2 = "basketball";
public String str3 = "all";
public ReflectPoint(int x,int y)
{
super();
this.x = x;
this.y = y;
}
public int hashCode()
{
final int prime = 31;
int result = 1;
result = prime*result + x;
result = prime*result + y;
return result;
}
public boolean equals(Object obj)
{
if(this==obj)
return true;
if(obj==null)
return false;
if(getClass()!=obj.getClass())
return false;
final ReflectPoint other = (ReflectPoint)obj;
if(x!=other.x)
return false;
if(y!=other.y)
return false;
return true;
}
public String toString()
{
return str1+"......"+str2+"......"+str3+"......";
}
}
public class ReflectTest2
{
public static void main(String args[])
{
Collection collections = new ArrayList();
ReflectPoint pt1 = new ReflectPoint(3,3);
ReflectPoint pt2 = new ReflectPoint(5,5);
ReflectPoint pt3 = new ReflectPoint(3,3);
collections.add(pt1);
collections.add(pt2);
collections.add(pt3);
collections.add(pt1);
System.out.println(collections.size());//打印結果爲2
}
}
由此可見,加上hashCode方法後,如果兩個對象的哈希碼相等,則兩者屬於同一對象,屬於重複,所以打印結果爲2。
注意:
當一個對象被存儲到HashSet集合後,就不能修改這個對象中的那些參與計算哈希值的字段了,否則,對象修改後的哈希值與最初存儲進HashSet集合時的哈希值就不同了,這種情況下,即使在contains方法使用該對象的當前引用作爲的參數去HashSet集合中檢索對象,也將返回找不到對象的結果,這也會導致無法從HashSet集合中單獨刪除當前對象,從而造成內存泄露。
示例:4:
修改上述代碼:
public class ReflectTest2
{
public static void main(String args[])
{
Collection collections = new HashSet();
ReflectPoint pt1 = new ReflectPoint(3,3);
ReflectPoint pt2 = new ReflectPoint(5,5);
ReflectPoint pt3 = new ReflectPoint(3,3);
collections.add(pt1);
collections.add(pt2);
collections.add(pt3);
collections.add(pt1);
pt1.y = 7;
collections.delete(pt1);
System.out.println(collections.size());//打印爲2
}
}
此時改變了pt1中屬性y的值,此時pt1的哈希碼變了,因此找不到剛存入時pt1的哈希碼了,因此pt1實際上並未被刪除,如此下去,會出現內存泄露。
當不改變存入的對象的跟哈希碼關聯的屬性時,可以正確的刪除pt1.
示例5:
public class ReflectTest2
{
public static void main(String args[])
{
Collection collections = new HashSet();
ReflectPoint pt1 = new ReflectPoint(3,3);
ReflectPoint pt2 = new ReflectPoint(5,5);
ReflectPoint pt3 = new ReflectPoint(3,3);
collections.add(pt1);
collections.add(pt2);
collections.add(pt3);
collections.add(pt1);
collections.delete(pt1);
System.out.println(collections.size());//打印結果爲1
}
}
此爲hashCode的用法和作用,希望大家能加深理解。