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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© ゞSunペ果果つ 中级黑马   /  2013-5-4 09:41  /  2164 人查看  /  16 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 ゞSunペ果果つ 于 2013-5-5 07:09 编辑
  1. package demo;
  2. import java.util.*;

  3. public class Demo3 {

  4. public static void main(String[] args) {
  5.   
  6. Collection<TwoPoint>  c=new HashSet<TwoPoint>();
  7.                 TwoPoint t1=new TwoPoint(3,5);
  8.                 TwoPoint t2=new TwoPoint(3,6);
  9.                 TwoPoint t3=new TwoPoint(3,7);
  10.                
  11.                 c.add(t1);
  12.                 c.add(t2);
  13.                 c.add(t3);
  14.                
  15.                 System.out.println(c.size());
  16.                 t2.y=8;//如果把这里改成5(这里是疑惑的部分)
  17.                 c.remove(t2);
  18.                 System.out.println(c.size());
  19.                 Iterator<TwoPoint> sets=c.iterator();
  20.                 while(sets.hasNext()){
  21.                         TwoPoint tp=sets.next();
  22.                         System.out.println(tp);
  23.                 }
  24.         }

  25. }
  26. class TwoPoint{
  27. //覆写了hashCode()方法
  28.         public int hashCode() {
  29.                 final int prime = 31;
  30.                 int result = 1;
  31.                 result = prime * result + x;
  32.                 result = prime * result + y;
  33.                 return result;
  34.         }
  35.         //覆写了equals()方法
  36.         public boolean equals(Object obj) {
  37.                 if (this == obj)
  38.                         return true;
  39.                 if (obj == null)
  40.                         return false;
  41.                 if (getClass() != obj.getClass())
  42.                         return false;
  43.                 TwoPoint other = (TwoPoint) obj;
  44.                 if (x != other.x)
  45.                         return false;
  46.                 if (y != other.y)
  47.                         return false;
  48.                 return true;
  49.         }
  50.         int x;
  51.         int y;
  52.         TwoPoint(int x,int y){
  53.                 this.x=x;
  54.                 this.y=y;
  55.         }
  56.         public String toString(){
  57.                 return x+"..."+y;
  58.         }
  59. }
  60. //我想说的是,如果改成t2.y=8;删除t2的时候,它是找不到了,所以集合的大小还是3,那如果我把t2.y=5;这样
  61. //集合的大小变成了2,我是不是可以认为,再删除t2的时候根本没有找到t2,而是直接把t1给删了?
  62. //为什么我会这样想?第一:如果把t2.y=8;改成一个不相关的数字,大小没有改变,说明他找不到集合中t2以前
  63. //的数据了对么?那我恰好给他改成已经纯在的t1的数据(让他们数据相等),它是不是会将t1中数据删了?
  64. //求高手解释



  65. //我个人觉得,刚才看了一下覆写的hashCode()方法,当把值改成已经存在在集合中的数据所指的话,确实是会取出来,是把t1的数据给移除了为什么我这样说?
  66. 简单测试一下,把t2.y=5;以后,移除一下试一试,是不是true?是
  67. 那有人就会说了,那也不定移除的是t1的数据啊,那好,你在c.remove(t1);一下,也就是此时我正常的移除我的t1,这样合情合理吧?结果那?false!为什么?因为他的数据被t2.y=5,修改以后给移除了。!

  68. 简单的说就是
  69. t2.y=5;
  70. c.remove(t2);  //true
  71. c.remove(t1); //false
  72. 你们懂得(感谢大家的谈论,一起进步)
复制代码

评分

参与人数 1技术分 +1 收起 理由
张熙韬 + 1

查看全部评分

16 个回复

倒序浏览
本帖最后由 xiewen 于 2013-5-4 10:23 编辑

你这道题太好了!
回复 使用道具 举报
本帖最后由 strawberry2013 于 2013-5-4 10:45 编辑

这个问题的关键就在与remove元素是否成功!
    boolean remove(Object o)   如果 set 中存在指定的元素,则将其移除(可选操作)。更确切地讲,如果此 set 中包含满足 (o==null ? e==null : o.equals(e)) 的元素 e,则移除它。如果此 set 包含指定的元素(或者此 set 由于调用而发生更改),则返回 true(一旦调用返回,则此 set 不再包含指定的元素)。
       当 t2.y = 5;时,进行(o==null ? e==null : o.equals(e) 判断,为true,也不进行hashCode和equals判定
      当t2.y = 8;时,(o==null ? e==null : o.equals(e) 为false,即System.out.println(c.equals(t2));为false,即不包含t2,c.contains(c2)也为false,但是t2在堆中信息依然存在,信息可以输出
  1. public static void main(String[] args) {
  2.   
  3. Collection<TwoPoint>  c=new HashSet<TwoPoint>();
  4.                 TwoPoint t1=new TwoPoint(3,5);
  5.                 TwoPoint t2=new TwoPoint(3,6);
  6.                 TwoPoint t3=new TwoPoint(3,7);
  7.                
  8.                 c.add(t1);
  9.                 c.add(t2);
  10.                 c.add(t3);
  11.                
  12.                 System.out.println(c.size());
  13.                 t2.y= 5;//
  14.                 System.out.println(c.remove(t2));   //判断是否移除成功!
  15.                 System.out.println(c.size());
  16.                 Iterator<TwoPoint> sets=c.iterator();
  17.                 while(sets.hasNext()){
  18.                         TwoPoint tp=sets.next();
  19.                         System.out.println(tp);
  20.                 }
复制代码

评分

参与人数 1技术分 +1 收起 理由
张熙韬 + 1

查看全部评分

回复 使用道具 举报
我理解的也是这样的,如果改成t2.y=5的话,t2指向的对象与t1相同,也就是说t1==t2的结果是true,
c.remove(t2);遍历集合,找到t2这个引用所指向的对象,也就是t1所指向的对象,然后將之删除。
回复 使用道具 举报
本帖最后由 孙胜 于 2013-5-4 11:59 编辑

看看我做的实验。透彻的分析了下HashSet的特点:
  1. package demo;
  2. import java.util.*;

  3. public class Demo3 {

  4. public static void main(String[] args) {
  5.   
  6. Collection<TwoPoint>  c=new HashSet<TwoPoint>();
  7.                 TwoPoint t1=new TwoPoint(3,5);
  8.                 TwoPoint t2=new TwoPoint(3,6);
  9.                 TwoPoint t3=new TwoPoint(3,7);
  10.                
  11.                 c.add(t1);
  12.                 c.add(t2);
  13.                 c.add(t3);
  14.                
  15.                 System.out.println("集合的大小是:"+c.size());
  16.                 System.out.println("t1的hashcode是:"+t1.hashCode());
  17.                 System.out.println("t2的hashcode是:"+t2.hashCode());
  18.                 System.out.println("t3的hashcode是:"+t3.hashCode());
  19.                
  20.                 t2.y=8;
  21.                
  22.                 //测试修改后t2的hashcode
  23.                 System.out.println("t2的hashcode是:"+t2.hashCode());
  24.                
  25.                
  26.                 //不管是调用contains还是remove都会在集合中先去找t2的
  27.                 //显然没有找到。所以这两个方法都是false
  28.                 System.out.println(c.contains(t2));
  29.                 System.out.println(c.remove(t2));
  30.                
  31.                
  32.                 System.out.println("集合的大小是:"+c.size());
  33.                
  34.                
  35.               //如果把这里改成5
  36.                 t2.y =5;
  37.                 System.out.println(c);
  38.                 //看结果是[3...5, 3...5, 3...7]。
  39.                 //此时t2的hashcode和集合中t1的相同,但是t2在集合中的hashcode并不改变,不论这个对象的hashcode是多少
  40.                
  41.                
  42.                 c.remove(t2);
  43.                 System.out.println(c);
  44.                 //这个时候你remove(t2),我觉得删除的是t1,t2永远都删除不掉了
  45.                
  46.                 //验证t1已经删除了
  47.                 System.out.println(c.remove(t1));
  48.         }

  49. }
  50. class TwoPoint{
  51. //覆写了hashCode()方法
  52.         public int hashCode() {
  53.                 final int prime = 31;
  54.                 int result = 1;
  55.                 result = prime * result + x;
  56.                 result = prime * result + y;
  57.                 return result;
  58.         }
  59.         //覆写了equals()方法
  60.         public boolean equals(Object obj) {
  61.                 if (this == obj)
  62.                         return true;
  63.                 if (obj == null)
  64.                         return false;
  65.                 if (getClass() != obj.getClass())
  66.                         return false;
  67.                 TwoPoint other = (TwoPoint) obj;
  68.                 if (x != other.x)
  69.                         return false;
  70.                 if (y != other.y)
  71.                         return false;
  72.                 return true;
  73.         }
  74.         int x;
  75.         int y;
  76.         TwoPoint(int x,int y){
  77.                 this.x=x;
  78.                 this.y=y;
  79.         }
  80.         public String toString(){
  81.                 return x+"..."+y;
  82.         }
  83. }
复制代码
输出结果:

集合的大小是:3
t1的hashcode是:1059
t2的hashcode是:1060
t3的hashcode是:1061
t2的hashcode是:1062
false
false
集合的大小是:3
[3...5, 3...5, 3...7]
[3...5, 3...7]
false

点评

是我少考虑了一部,把t2改成t1时候remove()方法的查找指针在t1用复写equals()的比较了下,他equals()方法里面条件都没满足而返回了true,remove()就把t1删了  发表于 2013-5-4 14:52
这边的t1是没删除的,相信我,已经是false了!!  发表于 2013-5-4 13:59

评分

参与人数 1技术分 +1 收起 理由
张熙韬 + 1

查看全部评分

回复 使用道具 举报
我来说说吧,你的意思是理解错了,你要删除t2调用remove()方法,他是不会把你的t1给删除的,要是能把你的t1删了
那么这个方法就存在严重的安全隐患,remove()方法在执行时候会调用equals()方法来判断是否有这个元素
(o==null ? e==null : o.equals(e)) 这是remove()的判断条件,里面的o表示要删的元素,里面的e是代表set集合里面的元素
而你把equals()给覆盖了,程序调用remove()方法时候是依据你的equals()来判断的,看看你的equals()
当你t2里面的y改成9的时候,在你的equals()里面执行的是:
if (y != other.y)
return false;
这既然返回false了,remove()方法就认为不是你要删除的,当然是不能删除。
而你把t2改成5了,那么你的equals()只执行的是最后一条return true;这句,那个既然是true,当然就符合remove()的判断
认为是你要删除的元素,所以把你的t2删了,而不是把你的t1删了

评分

参与人数 1技术分 +1 收起 理由
张熙韬 + 1

查看全部评分

回复 使用道具 举报
xiewen 发表于 2013-5-4 10:19
你这道题太好了!

谢谢,看张老师的视频,他说是改变了y的值就无法从集合中移除,他说移除的时候是根据区域里找的,那我就想,如果把y改成其他区域的值,执行移除的时候会不会把其他区域的移除,所以问题就来了.......
回复 使用道具 举报
xuluheng718 发表于 2013-5-4 13:43
我来说说吧,你的意思是理解错了,你要删除t2调用remove()方法,他是不会把你的t1给删除的,要是能把你的t1 ...

既然是把t2删了,也就是说他可以从集合中找到这个改变后的t2对么?既然t2.y=5的时候可以找到,那为什么t2.y=8的时候却找不到集合中的这个数了那?
回复 使用道具 举报
孙胜 发表于 2013-5-4 11:55
看看我做的实验。透彻的分析了下HashSet的特点:输出结果:

集合的大小是:3

其实我也是觉得它找错了,把t1给删了,但是楼下的哥们说不是,现在我也 不清楚,继续实验中...
回复 使用道具 举报
郑雪 发表于 2013-5-4 10:45
我理解的也是这样的,如果改成t2.y=5的话,t2指向的对象与t1相同,也就是说t1==t2的结果是true,
c.remove( ...

:lol开始我也是这样想的。
回复 使用道具 举报
strawberry2013 发表于 2013-5-4 10:42
这个问题的关键就在与remove元素是否成功!
    boolean remove(Object o)   如果 set 中存在指定的元素, ...

看完你写的,我觉得你那我的理解就是正确的了,确实是把t1误删了是这样么?
回复 使用道具 举报
ゞSunペ果果つ 发表于 2013-5-4 14:26
谢谢,看张老师的视频,他说是改变了y的值就无法从集合中移除,他说移除的时候是根据区域里找的,那我就 ...

我也看了张老师的视频是那样说的,你能发现这个问题你挺厉害的
回复 使用道具 举报
ゞSunペ果果つ 发表于 2013-5-4 14:28
既然是把t2删了,也就是说他可以从集合中找到这个改变后的t2对么?既然t2.y=5的时候可以找到,那为什么t2 ...

是我错了,又验证了次,把t2的值改成和t1时候确实吧t1给删了,因为删除时候是把指针放在集合开始处根据你复写的equals()开始找,条件符合就把t1给删了,因为你的equals()里面,所有条件不符合时候返回的ture,所以remove()返回的是true()
回复 使用道具 举报
xuluheng718 发表于 2013-5-4 14:49
是我错了,又验证了次,把t2的值改成和t1时候确实吧t1给删了,因为删除时候是把指针放在集合开始处根据你 ...

嗯也验证了,你确实是错了,我也改了信息了,我有个自己验证的方法,你可以看看,我们一起谈论,互相学习,谢谢了,我相信,以后我们谁不会忘记这个事情,这才是自己的知识
回复 使用道具 举报
xiewen 发表于 2013-5-4 14:37
我也看了张老师的视频是那样说的,你能发现这个问题你挺厉害的

呵呵,就是看着想到了,就动手自己写代码试一试,结果更疑惑了,呵呵就贴出来了,刚才测试一下,我想的确实还是对的
回复 使用道具 举报
ゞSunペ果果つ 发表于 2013-5-4 14:54
呵呵,就是看着想到了,就动手自己写代码试一试,结果更疑惑了,呵呵就贴出来了,刚才测试一下,我想的确 ...

没复写hashCode()和equals()这两个方法用集合本身的方法是不会出现这个问题的,是你复写equals()方法的时候
出现的安全隐患
回复 使用道具 举报
其实三楼的那位说的很好了、、、
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马