A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 张扬123 中级黑马   /  2012-7-25 22:21  /  1328 人查看  /  6 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 张扬123 于 2012-7-26 00:26 编辑

代码如下:
  1. import java.util.*;
  2. public class Hacode {

  3. public static void main(String[] args) {
  4. HashSet<Cat> hs=new HashSet<Cat>();
  5. Cat a1=new Cat("aaa",1);
  6. Cat a2=new Cat("aaa",1);
  7. Cat a3=new Cat("bbb",2);
  8. Cat a4=new Cat("bbb",2);
  9. hs.add(a1);
  10. hs.add(a2);
  11. hs.add(a3);
  12. hs.add(a4);
  13. hs.add(a1);

  14. System.out.println(hs.size());
  15. a1.age=22;
  16. hs.remove(a2);
  17. System.out.println(hs.size());

  18. }
  19. }
  20. class Cat {

  21. String name;
  22. int age;
  23. public Cat(String n,int a){
  24. name=n;
  25. age=a;
  26. }

  27. public int hashCode() {
  28. final int PRIME = 31;
  29. int result = 1;
  30. result = PRIME * result + age;
  31. result = PRIME * result + ((name == null) ? 0 : name.hashCode());
  32. return result;
  33. }
  34. @Override
  35. public boolean equals(Object obj) {
  36. if (this == obj)
  37. return true;
  38. if (obj == null)
  39. return false;
  40. if (getClass() != obj.getClass())
  41. return false;
  42. final Cat other = (Cat) obj;
  43. if (age != other.age)
  44. return false;
  45. if (name == null) {
  46. if (other.name != null)
  47. return false;
  48. } else if (!name.equals(other.name))
  49. return false;
  50. return true;
  51. }

  52. }
复制代码
为什么明明已经把a1给remove了还是输出hs的size是2呢?我只知道这与hashcode有关系,但是真的没彻底搞明白。

评分

参与人数 1技术分 +1 收起 理由
蒋映辉 + 1

查看全部评分

6 个回复

倒序浏览
你这里删除的是a2。hs.remove(a2);
如果删除先把a1的age属性改了之后再删除a1,确实是这样的,
因为他是hashSet集合。是根据哈希算法来算出的来哈希值来存储的。你改了他age属性。
而他的age属性又参加了哈希值的运输,hashCode()也就是你重写的这个方法。
他算出来的哈希值就变了,而HashSet集合里面存储的是他以前的哈希值。无法映射到a1了。
也就是找不到了这个a1元素了,所有也就无法删除了。

评分

参与人数 1技术分 +1 收起 理由
蒋映辉 + 1

查看全部评分

回复 使用道具 举报
本帖最后由 贾成龙 于 2012-7-25 22:55 编辑


hashCode()中你想改了a1的属性,又删除了a2后,这样再删除a1时,由于a1没有被找到所以还是2.
回复 使用道具 举报
因为你修改了age的值,而age是参加了hashcode值的运算的,新的hashcode与原来的不一样,hashset无法找到元素,remove方法便失败了
还造成了内存泄露 = =
回复 使用道具 举报
周玉龙 发表于 2012-7-25 22:32
你这里删除的是a2。hs.remove(a2);
如果删除先把a1的age属性改了之后再删除a1,确实是这样的,
因为他是has ...

虽然说起来比较绕,但是大概也明白了。谢谢。
回复 使用道具 举报
王艺霖 发表于 2012-7-25 22:34
重复的有两个即a1和a2重复a3和a4重复 进行存储的时候首先会调用hashcode()方法判断里面的hash值是否一致不 ...

不小心晕了一下。。。谢谢指教。
回复 使用道具 举报
徐帅 中级黑马 2012-7-25 23:10:04
7#
楼主的问题原因是:
     一个对象被存储进HashSet集合以后,就不能修改这个对象中的那些参与计算哈希值的字段了,否则对象修改后的哈希值
  与最初存储的进HashSet集合中的哈希值就不同了,所以无法删除当前对象

内存泄露:
    这种情况下,即使在contains方法下用该对象的引用作为参数去HashSet集合中检索对象,也将返回找不到对象的结果,这
  也会导致无法从HashSet集合中无法单独删除当前对象,从而导致内存泄露
  所以这样的问题是很危险的,应加倍注意!!!

评分

参与人数 1技术分 +1 收起 理由
韦念欣 + 1 赞一个!

查看全部评分

回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马