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;
  }
}
public class MapIt {
  public static void main(String[] args) {
    Set<KeyMaster> set = new HashSet<KeyMaster>();
    KeyMaster k1 = new KeyMaster(1);
    KeyMaster k2 = new KeyMaster(2);
    set.add(k1);
    set.add(k2);
    k2.i = 1;
    set.remove(k1);
    set.remove(k2);
    System.out.println(set.size());
    List<KeyMaster> list = new ArrayList<KeyMaster>();
    k1 = new KeyMaster(1);
    k2 = new KeyMaster(2);
    list.add(k1);
    list.add(k2);
    k2.i = 1;
    list.remove(k1);
    list.remove(k2);
    System.out.println(list.size());
  }
}

解决方案 »

  1.   

    结果:
    1
    0个人理解:此类实现 Set 接口,由哈希表(实际上是一个 HashMap 实例)支持,也就是说HashSet在很多方法都是有HashMap实现的。实际上在remove方法上就是这样:
        
        public boolean remove(Object o) {
    return map.remove(o)==PRESENT;
        }这里的Map就是HashMap的实例。
    HashMap是基于哈希表的 Map 接口的实现。此实现提供所有可选的映射操作。并且实现假定哈希函数将元素正确分布。所以可以说明在HashMap中这些元素是有HashCode来映射的。那么在程序中hashCode的重载,导致了第二次remove的时候实际上没有像想象中的移除第二个元素。在ArrayList中的是按照对象来定义的。可能说的不明白,也可能有不对的地方,欢迎斧正。
      

  2.   

    hash分布,导致remove不会到hashCode==2的地方,也就不会移除那个地方的对象。所以第一个结果长度为1
    第二个没啥,他是逐个判断的。结果为0hashCode的算法千万不要和内部的可变的属性关联,非常容易引起内存泄漏和程序运行异常。
      

  3.   

    按照各位楼上的 说法 那是否有几率一个也是0呢  hash分布到底时 如何分布地啊 
      

  4.   

    citli 说得对
    jdk中源码
    看一下注释就知道了
    由于hashcode改变了
    无法找到原来的对象
    删除失败 你可以在你的代码中直接
    System.out.println(set.remove(k2));
    结果为false    /**
         * Removes the specified element from this set if it is present.
         *
         * @param o object to be removed from this set, if present.
         * @return <tt>true</tt> if the set contained the specified element.
         */
        public boolean remove(Object o) {
    return map.remove(o)==PRESENT;
        }
      

  5.   

    KeyMaster k1 = new KeyMaster(1);
    //新建k1
    KeyMaster k2 = new KeyMaster(2);
    //新建k2
    set.add(k1);
    //将k1加到set 中
    //加到哪里呢?调用hashCode() 得到1;所以加到”1“位置。
    set.add(k2);
    //将k2加到set中
    //加到哪里呢?调用hashCode() 得到2;所以加到”2“位置。
    k2.i = 1;
    //更改k2的i=1;
    //即:只是更改了k2的i值由2变为了1.k2在set中的位置并未改变,依然是:”2“位置
    set.remove(k1);
    //要删除k1
    //到哪个位置删除k1呢?调用hashCode() 得到1;所以删除”1“位置。

    set.remove(k2);
    //要删除k2
    //到哪个位置删除k2呢?调用hashCode() 得到1;所以删除”1“位置。
    //"1"位置根本就没有东西了,所以删除失败,返回:false
    /////如:System.out.println(set.remove(k2););输出"false"

    System.out.println(set.size());
    //set的"2"位置还有一个k2呢。当然输出1了。
      

  6.   

    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;
    }
    }public class MapIt {
    public static void main(String[] args) {
    Set<KeyMaster> set = new HashSet<KeyMaster>();
    KeyMaster k1 = new KeyMaster(1);
    //新建k1
    KeyMaster k2 = new KeyMaster(2);
    //新建k2
    set.add(k1);
    //将k1加到set 中
    //加到哪里呢?调用hashCode() 得到1;所以加到”1“位置。
    set.add(k2);
    //将k2加到set中
    //加到哪里呢?调用hashCode() 得到2;所以加到”2“位置。
    k2.i = 1;
    //更改k2的i=1;
    //即:只是更改了k2的i值由2变为了1.k2在set中的位置并未改变,依然是:”2“位置
    set.remove(k1);
    //要删除k1
    //到哪个位置删除k1呢?调用hashCode() 得到1;所以删除”1“位置。

    set.remove(k2);
    //要删除k2
    //到哪个位置删除k2呢?调用hashCode() 得到1;所以删除”1“位置。
    //"1"位置根本就没有东西了,所以删除失败,返回:false
    /////如:System.out.println(set.remove(k2););输出"false"

    System.out.println(set.size());
    //set的"2"位置还有一个k2呢。当然输出1了。


    //以下的看ls
    List<KeyMaster> list = new ArrayList<KeyMaster>();
    k1 = new KeyMaster(1);
    k2 = new KeyMaster(2);
    list.add(k1);
    list.add(k2);
    k2.i = 1;
    list.remove(k1);
    list.remove(k2);
    System.out.println(list.size());
    }
    }
      

  7.   

    感谢21楼lord_is_layuping的详细讲解
    受教了啊!谢谢!
      

  8.   


     Please note the time when the hashCode() method of k1 and k2 were called.    o. create k1, k2, which k1.i=1, k2.i=2    o. add k1 to set, k1.hashCode() will be called, so the set find a proper place according to k1's hashCode, a.k.a. "1".    o. add k2 to set, k2.hashCode() will be called, it is "2", so the set find another place for k2.    o. change k2.i=1, watch out here, the "place" where k2 reside in the set will NOT change! there is NO dynamic duplicate check nor event notification in set.
       回复太快!如果你是恶意刷楼,将会受到严厉惩罚!ft
        o. delete k1, k1.hashCode() will be called once again. because the nature of set, the set will NOT search through all the background hashmap to delete all object which has "1" as hashcode. so there will be ONLY one object being deleted. k2 will NOT be deleted althought it DOES has a hashcode=1, but it's place in the set is according to "2".    o. now there is only k2 in the set, which's Key place in the set is "2", although in the mean time it has a hashcode "1".    o. trying to delete k2, this time k2.hashCode() will be called again, but there is not such object in the set with "1" as key, so deletion FAILED.    o. change k2.i=2    o. try to delete k2 again, this time we got a "2" from k2.hashCode(), so we can directly find the k2 object in the set, because there IS a key ojbect in the coressponding place to "2". so deletion SUCCESSED.