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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© Jim-剣◆﹏ 高级黑马   /  2013-11-29 13:55  /  3588 人查看  /  11 人回复  /   1 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 Jim-剣◆﹏ 于 2013-11-30 00:22 编辑

今早回复一帖子,发现一问题
我先说说我对hashSet对去除重复元素的看法,如有不对,大伙给我指出来
hashSet集合添加重复对象的识别方法是:
首先根据对象的hashCode值进行比较
如果hashCode值不同,则认为是不同的对象,直接添加进hashSet集合中
如果hashCode值相同,则继续用对象的equals方法比较,结果返回true则认为对象相同,添加失败,返回false则认为对象不同,添加成功


如果添加的对象没有覆写hashCode方法,那么此时的对象则是继承Object类的hashCode方法(经过查阅百度和API文档,得知Object中的hashCode方法是一个抽象方法,但是最终的实现是更具对象的内存地址值转化成一个int类型的值),hashCode值可以直观看成是对象内存地址值
如果添加的对象没有覆写equals方法,那么此时对象也是继承Object类的equals方法,进查阅API和源码,Object类中的equals方法内部实现是通过“=”比较两个对象的内存地址来实现的。
运行以下代码

  1. import java.util.*;

  2. class ReflectPoint {

  3.         private int x;
  4.         private int y;

  5.         ReflectPoint(int x, int y) {
  6.                 this.x = x;
  7.                 this.y = y;
  8.         }

  9.         @Override
  10.         public boolean equals(Object obj) {
  11.                 System.out.println("hashCode一致,调用equals");

  12.          return false;
  13.                
  14.         }


  15. class CollectionDemo {

  16.         public static void main(String[] args) {
  17.                 myTestFunc();
  18.         }

  19.         static void myTestFunc() {

  20.                 Collection collections = new HashSet();
  21.                 ReflectPoint pt1 = new ReflectPoint(3, 3);
  22.                 ReflectPoint pt2 = new ReflectPoint(5, 5);
  23.                 ReflectPoint pt3 = new ReflectPoint(3, 3);
  24.                 ReflectPoint pt4 = pt1;

  25.                 System.out.println(collections.add(pt1));
  26.                 System.out.println(collections.add(pt2));
  27.                 System.out.println(collections.add(pt3));
  28.                
  29.                 System.out.println(collections.add(pt1));
  30.                 System.out.println(collections.add(pt4));
  31.                
  32.                 System.out.println(collections.size());

  33.         }
  34. }
复制代码

的对象覆写了equals,并且无论对象内容是否相同,固定返回false值
期待的结果应该是
添加:true
添加:true
添加:true
添加:true
添加:true
元素个数:5
但是运行结果为
添加:true
添加:true
添加:true
添加:false
添加:false
元素个数:3

也就是说,pt1和pt4不能被重复添加,
问题一:为什么呢?进行添加操作的时候,会检查对象的hashCode值和equals,pt4和pt1的hashCode值固然相等(输出pt4和pt1的hashCode值验证过),继而就应该执行equals(),而且equals必定返回false,所以,应该认为pt1和pt4是不同的对象,成功添加,这里为什么添加失败?

问题二::没有执行equals,因为没有执行输出语句System.out.println("hashCode一致,调用equals"),两对象的hashCode值一致,为啥不执行equals?以下修改并覆写hashCode方法
  1. class ReflectPoint {

  2.         private int x;
  3.         private int y;

  4.         ReflectPoint(int x, int y) {
  5.                 this.x = x;
  6.                 this.y = y;
  7.         }

  8.         @Override
  9.         public boolean equals(Object obj) {
  10.                 System.out.println("hashCode一致,调用equals");
  11.          return false;
  12. }

  13. @Override
  14.         public int hashCode() {
  15.                 // TODO Auto-generated method stub
  16.          return (this.x + this.y) * 31;
  17.         }
  18. }
复制代码






此时打印的结果为:
添加:true
添加:true
hashCode一致,调用equals
添加:true
hashCode一致,调用equals
添加:false
hashCode一致,调用equals
添加:false
元素个数:3
明显这次在hashCode值相同的情况下,程序调用了对象的equals方法
问题三:对象仍然添加失败,这是为何?

评分

参与人数 1技术分 +1 收起 理由
贺奕凯 + 1

查看全部评分

11 个回复

倒序浏览
Clare0621 发表于 2013-11-29 17:59
参见api文档Object类中equals方法介绍如下:
---------------------------------------------------------- ...

大神你是对的,一阵见血,一解释就懂,这么细节的东西还真的不容易察觉
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马