本帖最后由 创造命运 于 2014-4-22 17:50 编辑
请大家看看一下代码,就张老师在高新技术26一节讲的代码。对其中的几点现象我做了思考,与大家分享,同时也想知道大家的想法。
import java.util.*;
class ReflectPoint {
public int x = 3;
public int y = 5;
public ReflectPoint(){}
public ReflectPoint(int x, int y)
{
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;
ReflectPoint other = (ReflectPoint) obj;
if (x != other.x)
return false;
if (y != other.y)
return false;
return true;
}
}
class HashCodeTest {
public static void main(String[] args) {
ReflectPoint rp1 = new ReflectPoint(3, 3);
ReflectPoint rp2 = new ReflectPoint(5, 5);
ReflectPoint rp3 = new ReflectPoint(3, 3);
System.out.println(rp1.equals(rp3)); //显示调用equals方法,结果:true
Set hashSet = new HashSet();
hashSet.add(rp1);
hashSet.add(rp2);
hashSet.add(rp3);
hashSet.add(rp1);
//结果是2,但是在ReflectPoint类中重写HashCode及equals方法之前,结果是3
System.out.println(hashSet.size());
rp1.x = 7; //对象rp1中的x值改变了,那么它的hashCode值也变了。
hashSet.remove(rp1);
System.out.println(hashSet.size());//这里结果还是2,说明rp1元素没有成功删除
}
}
现象1、张老师演示过,将hashCode方法注释掉之前,hashSet这个集合里能够存储两个个元素:rp1,rp2;hashSet这个集合里能够存储三个元素:rp1,rp2,rp3。大家有没有思考为什么会这样呢?
于是我显示调用了equals方法:System.out.println(rp1.equals(rp3)); //显示调用equals方法,结果:true。说明什么?
我猜测,HashSet集合在添加元素的时候,先调用的是hashCode方法,如果hashCode值不相等,就不会调用equals方法,直接将该元素添加到集合中来;如果hashCode值相等了,再去调用equals方法判定是否要将该元素添加到集合中。
现象2、我在代码最后加了几行代码,如下
Iterator it = hashSet.iterator();
while(it.hasNext())
{
System.out.println(it.next());
}
将hashCode方法与remove语句注释,输出结果:
3
3
ReflectPoint [x=7, y=3]
ReflectPoint [x=3, y=3]
ReflectPoint [x=5, y=5];说明rp1,rp2,rp3都添加到集合了,并且rp1的x值也改变了。
只将hashCode方法注释,结果:
3
2
ReflectPoint [x=3, y=3]
ReflectPoint [x=5, y=5];集合中的元素是rp1,rp2,rp3。在默认的hashCode方法下,可以删除rp1
取消注释,结果:
2
2
ReflectPoint [x=7, y=3]
ReflectPoint [x=5, y=5];集合中的元素是rp1,rp2。重写hashCode方法后,不能删除rp1
分析:第一种情况好理解,同时还说明了,就算元素已经被添加到集合中,在外部还是可以对元素的属性进行操作。
第二种情况,rp1在它的x属性值改变之后,依然可以被删除。因为在默认的hashCode方法里,采用的是根据元素的地址通过某种算法得出的hashCode值。
即使rp1的x属性值被改变,但他的地址没有改变。所以在remove方法的底层调用hashCode方法时能够得出与在rp1被添加到集合时相同的hashCode值。在equals方法调用后也能返回true。所有可以被删除。
第三种情况,重写后的hashCode方法是根据元素的属性得到hashCode值。由于属性值改变,所有在被添加和被删除时所得到的hashcode值不等。也就找不到rp1了。同样由于hashcode值不等,也不会再去调用equals方法。
|
-
8.jpg
(167.86 KB, 下载次数: 19)
|