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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 陈国斌 中级黑马   /  2013-5-3 18:32  /  1575 人查看  /  4 人回复  /   1 人收藏 转载请遵从CC协议 禁止商业使用本文

一个对象存放在HashSet集合中后,再把它的某个属性值改掉,会导致删除该对象的动作失败,于是发生内存泄露,我想请问一下,具体的原因是下列哪种?
1、对象属性值的改变导致对象哈希值的变化,紧接着对象按照新的哈希值在集合中有了新的位置,而删除时,又是按照原来的位置去找,导致删除失败。
2、对象属性值的改变导致对象哈希值的变化,在删除时,按照新的哈希值对应的位置去找,而对象仍存在于原来的位置上,所以导致删除失败。
或者是其他的原因?
有什么办法能让更改某个属性值后,仍然能正常删除?请高手指点,感激不尽!

评分

参与人数 1技术分 +1 收起 理由
黄玉昆 + 1

查看全部评分

4 个回复

倒序浏览
尹桥印 发表于 2013-5-3 18:44
楼主又在找茬了。呵呵,楼主的帖子我觉得我都应该要收藏,因为问的问题都好有深度。先收藏了先 ...

哥们你再这么说,我都不敢问问题了,呵呵!我还是个刚开始学的菜鸟
回复 使用道具 举报
本帖最后由 刘胜寒 于 2013-5-3 21:32 编辑

对象的属性改变并没有立刻改变hash值的变化。
只是当去调用remove的时候才会改变hash值的变化。
  1. class A
  2. {
  3.         int  x,y;
  4.         A(int x,int y)
  5.         {
  6.                 this.x = x;
  7.                 this.y = y;
  8.         }
  9.         @Override
  10.         public int hashCode() {
  11.                 System.out.println(x+":"+y);
  12.                 final int prime = 31;
  13.                 int result = 1;
  14.                 result = prime * result + x;
  15.                 result = prime * result + y;
  16.                 return result;
  17.         }
  18.         @Override
  19.         public boolean equals(Object obj) {
  20.                

  21.                 System.out.println("equals");
  22.                 if (this == obj)
  23.                 {
  24.                         return true;
  25.                 }
  26.                         
  27.                 if (obj == null)
  28.                         return false;
  29.                 if (getClass() != obj.getClass())
  30.                         return false;
  31.                 A other = (A) obj;
  32.                 if (x != other.x)
  33.                         return false;
  34.                 if (y != other.y)
  35.                         return false;
  36.                 return true;
  37.         }
  38.         
  39. }

  40. public class Test{
  41.         public static void main(String[] arg)
  42.         {
  43.                 HashSet<A>  B = new HashSet<A>();
  44.                 A A1 = new A(2,3);
  45.                 A A2 = new A(3,2);
  46.                 A A3 = new A(3,4);
  47.                 A A4 = new A(4,3);
  48.                 B.add(A1);
  49.                 B.add(A2);
  50.                 B.add(A3);
  51.                 B.add(A4);
  52.                
  53.                 A4.x=7;
  54.                 System.out.println("A4 被修改");
  55.                 System.out.println(A4.x+"::::"+A4.y);
  56.                 System.out.println(B.contains(A4));
  57.                 System.out.println(B.remove(A4));
  58.                
  59.                
  60.         }
复制代码
hasset的源码
  1. <blockquote> public boolean remove(Object o) {
复制代码
看看是怎么现实remove的。通过正常途径添加到hashset的有一个固定一个标识PRESENT,当你的某属性改变的时候,标识肯定不是PRESENT。然后导致删除失败。

按照新的哈希值对应的位置去找,而对象仍存在于原来的位置上。



评分

参与人数 1技术分 +1 收起 理由
黄玉昆 + 1

查看全部评分

回复 使用道具 举报
答案是:
对象属性值的改变导致对象哈希值的变化,在删除时,按照新的哈希值对应的位置去找,而对象仍存在于原来的位置上,所以导致删除失败。

要想改变对象的属性,又能正常删除,明白删除对象依据hashCode去找的,而hashCode又是根据属性值来计算的,

所以,只要覆写的hashCode()方法中不使用你要改的那个属性即可,那你再改这个属性,就不影响hashCode的值了,所以也不影响集合找对象了,也可以查找和删除了.

评分

参与人数 1技术分 +1 收起 理由
黄玉昆 + 1

查看全部评分

回复 使用道具 举报
如果仍有问题,请继续追问,如果问题已解决,请将分类改为已解决,谢谢
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马