import java.util.*;
class KeyMaster{
public int i;
public KeyMaster(int i){this.i=i;}
public boolean equals(Object o){
return i==((KeyMaster)o).i;
}
public int hashCode(){
return i;
}
}class MapIt{
public static void main(String arg[]){
Set<KeyMaster>set=new HashSet<KeyMaster>();
KeyMaster k1=new KeyMaster(1);
KeyMaster k2=new KeyMaster(2);
set.add(k1);
set.add(k1);
set.add(k2);
set.add(k2);
System.out.print(set.size()+":");
k2.i=1;
System.out.print(set.size()+":");
set.remove(k1);
System.out.print(set.size()+":");
set.remove(k2);
System.out.println(set.size());
}
}
class KeyMaster{
public int i;
public KeyMaster(int i){this.i=i;}
public boolean equals(Object o){
return i==((KeyMaster)o).i;
}
public int hashCode(){
return i;
}
}class MapIt{
public static void main(String arg[]){
Set<KeyMaster>set=new HashSet<KeyMaster>();
KeyMaster k1=new KeyMaster(1);
KeyMaster k2=new KeyMaster(2);
set.add(k1);
set.add(k1);
set.add(k2);
set.add(k2);
System.out.print(set.size()+":");
k2.i=1;
System.out.print(set.size()+":");
set.remove(k1);
System.out.print(set.size()+":");
set.remove(k2);
System.out.println(set.size());
}
}
楼主所写的第一次add(k1),再add(k1),先判断这两个对像,因为相同,所以size=1;
再add(k2),因为k1与k2比较起来不相同,所以k2加进去了。size=2
再add(k2),先k1与k2,比较不同,然后k2与k2比较,他们相同,不加,size=1;
return i;
}
原因在这里,每次改变KeyMaster的i的时候,lz强制改变了hashCode的返回值,导致HashSet无法按照k2的原来HashCode找到该元素所在的位置,因此也就无法删掉k2~记住,在HashXXX系列的Map,Set,Tree,Table等结构中,系统是按照你存数据的时候生成的HashCode来查找位置的,这一系列的hashCode()方法一般是不允许手动区修改的~~
先抱怨一句,CSDN设置回复不能连续超过三次,昨晚当我想回答最后一个值的时候,却发表不了,原来我已经连续发了三篇回复……第四个是1而不是0,可以这么来考虑:
实际上HashSet的元素是放在HashMap中存储的,元素本身作为value,而key的值是由hashCode()的值计算出来的(暂且可以理解为就是这个值,对题目没有影响。如果想弄清楚,可以看HashSet的代码),所以往Set中添加元素的时候,HashMap中存的可以看作是<2, k2>(因为KeyMaster定义的hashCode就是返回i)。然后修改了k2的值以后,hashCode的值也相应变成1了,所以这时候再删除k2的时候,HashMap中找不到key为1的Entry了,所以Set的大小还是1。如果在main方法的最后再加上以下代码,就会输出0了。
k2.i=2;
set.remove(k2);
System.out.print(set.size());
set.remove(k1);
System.out.print(set.size()); 结果应该是0,但结果还是1呢,
你对k2赋值,可以改变它的hashCode,但他的存放位置已经固定,这点你没法改变,因此你只能用它原始的i值来找它的位置,k1,k2是两个对象,更不可能用set.remove(k1);System.out.print(set.size()); 来达到删掉k2的效果,即使他们的i值一样~
set.remove(k1);
System.out.print(set.size()); 结果应该是0,但结果还是1呢,---------------------------当然还是1假设想要删除k,删除的时候会判断k的hashCode()在HashMap中有没有匹配的,如果有,假设记为k',还要看一看k和k'是不是内容相同,即equals方法是不是会返回为真。如果是的话,才会在Set中删除。上面的程序中如果你删除k1,显然这两个条件不可能都满足(因为存在HashMap中的k'你是不能够改变的),所以大小还是1