关于Java中的 ==, equals(), hashCode()的作用

来源:互联网 发布:java正则表达式空格 编辑:程序博客网 时间:2024/06/05 02:09

1, == 号的作用

(1) 用来比较java基本类型是否相等, 但不包含基本类型的包装器类型,比如使用 new Integer(100) 方式创建两个Integer对象用==比较是为false的, 基本类型有三类:字符类型char,布尔类型boolean,数值类型int,float等等, 需要注意的是float和double基本类型的比较会涉及到精度处理的问题,最好是使用Float.compare方法和Double.compare方法

(2) 用来判断两个对象引用指向的内存地址是否相等,即是判断两个对象引用是否指向同一个对象(当对象引用为空值时同样适用);


2, equals()方法的作用

(1)对于Object对象,equals()方法内部使用 == 号判断源对象引用与参数引用是否一致:

public boolean equals(Object obj) {return (this == obj);}
即是判断是否是同一个对象。如果一个类没有重写equals()方法,那么它的equals方法实现是从Object根类继承下来的;

(2)对于基本类型的包装器类或String类,都重写了equals()方法,用于判断包装器对象或String对象的value属性值是否相等,下面是Integer类里面重写的equals()方法:

public boolean equals(Object obj) {if (obj instanceof Integer) {    return value == ((Integer)obj).intValue();}return false;}

(3)如果类重写了equals方法,那么同时要重写hashCode()方法,理由见下面第3点.


3,hashCode()的作用

返回一个叫作哈希码的整形值(在实际使用时要经过hash函数的再次运算),在Object类中,这是一个native方法,返回的值依赖于本地实现;

此方法的主要作用是使基于哈希表(也称为散列表)的集合能够正常工作, 这样的集合包括HashMap, HashSet, HashTable,在其他场合比较少用到;

原理:

在哈希表的存储实现中,用哈希码代表对象所在的一块存储区域,该存储区域可能还有其它的对象;

        如果要把一个对象(这个对象可以是HashSet的一个值对象valueS, 或者是HashMap的一个Entry<key对象, valueM对象>)放入哈希表的存储区,就要根据某种算法给该对象分配一个哈希码,这个哈希码正是valueS对象的hashCode()方法或key对象的hashCode()方法返回的值再经过特定规则的运算得到的, 然后就可以尝试将valueS对象或Entry放入该哈希码所对应的存储区域,这时就要调用valueS对象或key对象的equals方法,判断该存储区域中是否已含有相等的对象,如果有则不用再存储,如果没有则将对象放入.

        当要从HashMap里获取key对象所对应的valueM对象时,就要调用key对象的hashCode()方法获取到本地机器返回的整形值再计算出哈希码(哈希码对应存储区域地址下标),找到对应的存储区域,然后调用key对象的equals方法,与存储区里面的每个Entry对象的key对象进行比较,匹配则返回对应的valueM对象.

       因为在基于哈希表的集合中对象的equals方法与 hashCode 方法是配合使用的,所以在重写一个类的equals方法时要同时重写 hashCode 方法, java 的Object对象的相关规范如下:

(1)在应用程序的执行期间,只要对象的equals方法的比较操作所用到的信息没有被修改,那么对这同一个对象调用多次,hashCode方法都必须始终如一地返回同一个整数。在同一个应用程序的多次执行过程中,每次执行所返回的整数可以不一致。

(2)如果两个对象根据equals(Object)方法比较是相等的,那么调用这两个对象中任意一个对象的hashCode方法都必须产生同样的整数结果。

(3)如果两个对象根据equals(Object)方法比较是不相等的,那么调用这两个对象中任意一个对象的hashCode方法,则不一定要产生不同的整数结果。但是程序员应该知道,给不相等的对象产生截然不同的整数结果,有可能提高散列表的性能。

        总之重写hashCode方法的合格的做法是:根据equals(Object)方法比较相等的两个对象的hashCode方法要返回相等的值; 而高效的做法是: 在前面合格做法的基础上,给不相等的对象产生不同的整数结果.合格的做法让相等的对象聚焦到同一个存储区,不会造成元素的重复保存; 高效的做法使不相等的对象尽量分散在不同存储区域,提高整体存储区域的利用率和减少在单个存储区查找匹配对象的次数.

        要重写良好的hashCode方法,可参考<<Effective java 第二版>>中关于重写hashCode方法的内容; 对上面所提数据结构更形象深入的理解, 则应该了解HashMap, HashSet, HashTable中的基于链地址法处理冲突的哈希表的机制, 这里不作深入讨论.



原创粉丝点击