——- 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的用法和作用,希望大家能加深理解。