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());

}
}

解决方案 »

  1.   

    HASHSET先调用hashCode还是先equals()都不记得了。楼主只要知道hashSet是不会加重复的对像就行了,至于怎么样才算重复就看对像的这两个方法了,如果相同那么它是不会加进去的。原来有一个A在里边,现在加一个B进去,会判断A和B是否相同(调用那两个方法来判断),如果相同就不加进去了。size=1;反之就加进去,size=2;
    楼主所写的第一次add(k1),再add(k1),先判断这两个对像,因为相同,所以size=1;
    再add(k2),因为k1与k2比较起来不相同,所以k2加进去了。size=2
    再add(k2),先k1与k2,比较不同,然后k2与k2比较,他们相同,不加,size=1;
      

  2.   

    boolean add(E o)如果 set 中尚未存在指定的元素,则添加此元素(可选操作)。更正式地说,如果此 set 没有包含满足下列条件的元素 e,则向 set 中添加指定的元素 o:(o==null ? e==null :o.equals(e))。如果此 set 已经包含指定的元素,则该调用不改变此 set 并返回 false。结合构造方法上的限制,这就可以确保 set 永远不包含重复的元素。
      

  3.   

    AWUSOFT说明了第一个输出为什么是2对于第二“2”,可以这么考虑。Set里面有k1、k2,而Set知道k1、k2不相等。尽管这时程序通过k2.i=1;改变了k2所指对象的其中一个属性的值,从而使得k1.equals(k2)返回为true,但这时Set并不知道,所以不会把k1和k2中的某一个删除掉,所以大小还是为2。
      

  4.   

    至于第三个为什么是“1”,其实看一看HashSet的实现就明白。代码我不贴出来,不过它的remove代码最后是用到了HashMap的removeEntryForKey这个方法,在这个方法中只删除找到的第一个hash值相同的(对于本例而言,你可以认为是找到第一个i的值相同的),删除后返回为除。这样的话,尽管k1、k2是相等的(equals),但set.remove(k1);只会删除一个元素。如果上面的解释你不明白的话,可以这么来想:因为Set知道它里面的元素不是重复的,所以删除其中某个值的话最多只能删除一个元素。故,删除k1之后(删除成功),Set的大小变成了1。
      

  5.   

    public int hashCode() {
      return i;
    }
    原因在这里,每次改变KeyMaster的i的时候,lz强制改变了hashCode的返回值,导致HashSet无法按照k2的原来HashCode找到该元素所在的位置,因此也就无法删掉k2~记住,在HashXXX系列的Map,Set,Tree,Table等结构中,系统是按照你存数据的时候生成的HashCode来查找位置的,这一系列的hashCode()方法一般是不允许手动区修改的~~
      

  6.   

    终于又有人顶了~~
    先抱怨一句,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());
      

  7.   

    还是有点问题呢,按你说的思路,如果把最后该成
    set.remove(k1);
    System.out.print(set.size()); 结果应该是0,但结果还是1呢,
      

  8.   

    k1和k2是两个不同的对象,虽然他们的值一样,但他们的存放地址也不是一样的,set.remove(k1);只能删掉k1,要删掉k2,要k2.i=2;set.remove(k2);System.out.print(set.size());你再试一试结果~~~
    你对k2赋值,可以改变它的hashCode,但他的存放位置已经固定,这点你没法改变,因此你只能用它原始的i值来找它的位置,k1,k2是两个对象,更不可能用set.remove(k1);System.out.print(set.size()); 来达到删掉k2的效果,即使他们的i值一样~
      

  9.   

    还是有点问题呢,按你说的思路,如果把最后该成
    set.remove(k1);
    System.out.print(set.size()); 结果应该是0,但结果还是1呢,---------------------------当然还是1假设想要删除k,删除的时候会判断k的hashCode()在HashMap中有没有匹配的,如果有,假设记为k',还要看一看k和k'是不是内容相同,即equals方法是不是会返回为真。如果是的话,才会在Set中删除。上面的程序中如果你删除k1,显然这两个条件不可能都满足(因为存在HashMap中的k'你是不能够改变的),所以大小还是1