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

© 创造命运 中级黑马   /  2014-4-22 17:29  /  1086 人查看  /  0 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 创造命运 于 2014-4-22 17:50 编辑

请大家看看一下代码,就张老师在高新技术26一节讲的代码。对其中的几点现象我做了思考,与大家分享,同时也想知道大家的想法。
import java.util.*;
class ReflectPoint {
        public int x = 3;
        public int y = 5;
        public ReflectPoint(){}
        public ReflectPoint(int x, int y)
        {
                this.x = x;
                this.y = y;
        }
        public int hashCode() {
                final int prime = 31;
                int result = 1;
                result = prime * result + x;
                result = prime * result + y;
                return result;
        }
        public boolean equals(Object obj) {
                if (this == obj)
                        return true;
                if (obj == null)
                        return false;
                if (getClass() != obj.getClass())
                        return false;
                ReflectPoint other = (ReflectPoint) obj;
                if (x != other.x)
                        return false;
                if (y != other.y)
                        return false;
                return true;
        }
}
class HashCodeTest {
        public static void main(String[] args) {
                ReflectPoint rp1 = new ReflectPoint(3, 3);
                ReflectPoint rp2 = new ReflectPoint(5, 5);
                ReflectPoint rp3 = new ReflectPoint(3, 3);
               
                System.out.println(rp1.equals(rp3));    //显示调用equals方法,结果:true
               
                Set hashSet = new HashSet();
                hashSet.add(rp1);
                hashSet.add(rp2);
                hashSet.add(rp3);
                hashSet.add(rp1);
                //结果是2,但是在ReflectPoint类中重写HashCode及equals方法之前,结果是3
                System.out.println(hashSet.size());  
                rp1.x = 7;  //对象rp1中的x值改变了,那么它的hashCode值也变了。
                hashSet.remove(rp1);
                System.out.println(hashSet.size());//这里结果还是2,说明rp1元素没有成功删除
        }
}


现象1、张老师演示过,将hashCode方法注释掉之前,hashSet这个集合里能够存储两个个元素:rp1,rp2;hashSet这个集合里能够存储三个元素:rp1,rp2,rp3。大家有没有思考为什么会这样呢?
于是我显示调用了equals方法:System.out.println(rp1.equals(rp3));    //显示调用equals方法,结果:true。说明什么?
我猜测,HashSet集合在添加元素的时候,先调用的是hashCode方法,如果hashCode值不相等,就不会调用equals方法,直接将该元素添加到集合中来;如果hashCode值相等了,再去调用equals方法判定是否要将该元素添加到集合中。
现象2、我在代码最后加了几行代码,如下
Iterator it = hashSet.iterator();
while(it.hasNext())
{
        System.out.println(it.next());
}

将hashCode方法与remove语句注释,输出结果:
3
3
ReflectPoint [x=7, y=3]
ReflectPoint [x=3, y=3]
ReflectPoint [x=5, y=5];说明rp1,rp2,rp3都添加到集合了,并且rp1的x值也改变了。
只将hashCode方法注释,结果:
3
2
ReflectPoint [x=3, y=3]
ReflectPoint [x=5, y=5];集合中的元素是rp1,rp2,rp3。在默认的hashCode方法下,可以删除rp1

取消注释,结果:
2
2
ReflectPoint [x=7, y=3]
ReflectPoint [x=5, y=5];集合中的元素是rp1,rp2。重写hashCode方法后,不能删除rp1

分析:第一种情况好理解,同时还说明了,就算元素已经被添加到集合中,在外部还是可以对元素的属性进行操作。
第二种情况,rp1在它的x属性值改变之后,依然可以被删除。因为在默认的hashCode方法里,采用的是根据元素的地址通过某种算法得出的hashCode值。
即使rp1的x属性值被改变,但他的地址没有改变。所以在remove方法的底层调用hashCode方法时能够得出与在rp1被添加到集合时相同的hashCode值。在equals方法调用后也能返回true。所有可以被删除。
第三种情况,重写后的hashCode方法是根据元素的属性得到hashCode值。由于属性值改变,所有在被添加和被删除时所得到的hashcode值不等。也就找不到rp1了。同样由于hashcode值不等,也不会再去调用equals方法。


8.jpg (167.86 KB, 下载次数: 19)

8.jpg

评分

参与人数 1技术分 +1 收起 理由
黑妞~ + 1

查看全部评分

0 个回复

您需要登录后才可以回帖 登录 | 加入黑马