equals和hashcode
java当中所有的类都继承于Object这个基类,在object中的基类定义了一个equals方法,public boolean equals(Object obj) {
return (this == obj);}这个方法的初始行为是比较引用,但在一些类库中这个方法被覆盖掉了,如String,Integer,Date等在这些类中equals有其自身的实现,而不再是比较对象在栈内存中的地址(即引用)了,如果不覆盖,则equals默认行为是比较引用。对于引用数据类型之间进行equals比较,在没有覆盖equals方法的情况下,他们之间的比较还是基于对象的引用,因为object的equals方法也是用==进行比较的,所有比较后的结果与双等号的结果相同。
如果我们希望equals比较的不再是引用,我们就需要覆写equals方法。
equals 方法在非空对象引用上实现相等关系:
- 自反性:对于任何非空引用值
x,x.equals(x)都应返回true。 - 对称性:对于任何非空引用值
x和y,当且仅当y.equals(x)返回true时,x.equals(y)才应返回true。 - 传递性:对于任何非空引用值
x、y和z,如果x.equals(y)返回true,并且y.equals(z)返回true,那么x.equals(z)应返回true。 - 一致性:对于任何非空引用值
x和y,多次调用 x.equals(y) 始终返回true或始终返回false,前提是对象上equals比较中所用的信息没有被修改。 - 对于任何非空引用值
x,x.equals(null)都应返回false。
举一个覆写了equals的例子:
class Strudent{
private int age;
private String name;
......//构造函数以及setter和getter
public boolean equals(Object obj){
boolean result=false;
if(obj==null){//若传入的对象为空
result=false;
}
if(this==obj){//若传入的对象和Student对象的引用相同,则表示指向了同一个堆内存中的对象
result=true;
}
if(obj instanceof Student){//obj对象是否是Student类的实例
Student stu=(Student)obj;//将Object类向下转型为Student类
if(stu.getName().equals(this.name)&&stu.getAge()==this.age)//这里的equals方法调用的是String类库中已被覆写过的equals方法,因getName()返回的String类型的值
result=true;
}else{
result= false;
}
return result;
}
}
注意:当equals方法被覆写时,通常有必要覆写hashCode方法,以维护hashCode方法的常规规定,该协定声明相等的对象必须具有相等的哈希码。
上面代码中的hashCode()方法可以这样写:public int hashCode(){ return (this.name.hashCode()+this.age)*31;}
在覆写了equals方法的类中,必须也覆写hashCode方法,如果不覆盖“键”的hashCode()和equals(),那么使用散列的数据结构(HashSet, HashMap, LinkedHashSet, LinkedHashMap)就无法正确地处理你的“键”。
hashCode()这个方法也是在object类中定义的:public native int hashCode();
hashCode()是一个本地方法,它的实现与本地机器相关。hashCode()生成对象的哈希码值,它默认是使用对象的地址计算出的哈希码,返回的是整数类型,如果没有覆写hashCode()方法,任何对象的哈希码值都是不相等的。而设计hashCode的最重要的因素就是:无论何时,对同一个对象调用hashCode()都应该生成同样的值。如果在将一个对象用put()添加进HashMap时产生一个hashCode()值,而在用get()取出时却产生了另一个hashCode()值,那么就无法重新取得该对象了。所以,如果你的hashCode()方法依赖于对象中易变的数据,那么当数据变化时,hashCode就会生成一个不同的哈希码,相当于产生了一个不同的键。也不应该使hashCode()依赖于具有唯一性的对象信息,尤其是使用this的值,这只能产生很糟糕的hashCode(),因为这样做无法生成一个新的键,使之与put()中原始的键值对中的键相同。
要想使hashCode()实用,它的速度必须快,而且必须有意义。也就是说,它必须基于对象的内容生成哈希码。哈希码不必是独一无二的(应该更关注生成速度,而不是唯一性),但是通过hashCode()和equals(),必须能够完全确定对象的身份。
hashCode()的返回值(哈希码值)和equals()的关系如下:
如果x.equals(y)返回“true",那么x和y的hashCode()必须相等。
如果x.equals(y)返回”false",那么x和y的hashCode()有可能相等,也有可能不相等。
还有注意:String、Integer、Boolean、Double等这些类都覆写了equals和hashCode方法,这个两个方法是根据对象的内容来比较和计算哈希码值的。所以,主要对象的基本类型值相同,那么哈希码值就一定相同。
equals和hashcode的更多相关文章
- How to implement equals() and hashCode() methods in Java[reproduced]
Part I:equals() (javadoc) must define an equivalence relation (it must be reflexive, symmetric, and ...
- JAVA中用堆和栈的概念来理解equals() "=="和hashcode()
在学习java基本数据类型和复杂数据类型的时候,特别是equals()"=="和hashcode()部分时,不是很懂,也停留了很长时间,最后终于有点眉目了. 要理解equals() ...
- 关于equals、hashcode和集合类的小结
一.首先明确一点:equals()方法和hashcode()方法是Object类里的方法. 查看源码可以知道,在Object类中equals(obj)方法直接返回的是 this == obj 的值. ...
- Object方法equals、hashCode
java知识背景: 1)hashCode()方法返回的是Jvm的32位地址 2)==比较的是对象在jvm中的地址 3)Object的equals()比较的就是jvm物理地址 4)比较2个对象使用equ ...
- Java中的equals和hashCode方法
本文转载自:Java中的equals和hashCode方法详解 Java中的equals方法和hashCode方法是Object中的,所以每个对象都是有这两个方法的,有时候我们需要实现特定需求,可能要 ...
- Java提高篇——equals()与hashCode()方法详解
java.lang.Object类中有两个非常重要的方法: 1 2 public boolean equals(Object obj) public int hashCode() Object类是类继 ...
- Java中==、equals、hashcode的区别与重写equals以及hashcode方法实例(转)
Java中==.equals.hashcode的区别与重写equals以及hashcode方法实例 原文地址:http://www.cnblogs.com/luankun0214/p/4421770 ...
- java中equals和hashCode方法的解析
解析Java对象的equals()和hashCode()的使用 前言 在Java语言中,equals()和hashCode()两个函数的使用是紧密配合的,你要是自己设计其中一个,就要设计另外一个.在多 ...
- Java实战equals()与hashCode()
一.equals()方法详解 equals()方法在object类中定义如下: 代码 public boolean equals(Object obj) { return (this == obj); ...
- 一次性搞清楚equals和hashCode
前言 在程序设计中,有很多的“公约”,遵守约定去实现你的代码,会让你避开很多坑,这些公约是前人总结出来的设计规范. Object类是Java中的万类之祖,其中,equals和hashCode是2个非常 ...
随机推荐
- COJ 2108 Day7-例1
Day7-例1 难度级别:B: 运行时间限制:1000ms: 运行空间限制:256000KB: 代码长度限制:2000000B 试题描述 在计算机中,CPU只能和高速缓存Cache直接交换数据.当 ...
- BZOJ1621: [Usaco2008 Open]Roads Around The Farm分岔路口
1621: [Usaco2008 Open]Roads Around The Farm分岔路口 Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 521 S ...
- 一键安装mysql5.6
#!/bin/bash # @Name:install_mysql.sh # @Author:Eivllom # @Create -- # @Modify -- app_soft="/app ...
- Android RSA加密对象数据
前几天说了手头项目用MD5和双向加密DES来进行加密的,因为产品是在不断的改造中完善的.考虑到DES和MD5加解密还是会存下一定的风险,于是产品一拍,不行,听你们说MD5加密是不安全的,咱们产品以后做 ...
- Redis结合EntityFramework结合使用的操作类
最近一段时间在研究redis. 各种不懂, 各种问题.也看了N多的资料. 最终参照着 张占岭 的博客 http://www.cnblogs.com/lori/p/3435483.html 写 ...
- www.chenbowenblog.com 博客地址转移
我的新博客地址是 www.chenbowenblog.com 欢迎来访.
- THOMAS MASON--英国顶级衬衫面料品牌
欧尚时光 THOMAS MASON--英国顶级衬衫面料品牌 2014-01-26 欧尚时光 今天为大家介绍英国顶级衬衫面料厂商:THOMAS MASON(托马斯·梅森).THOMAS MAS ...
- How many ways?? - hdu2157(矩阵快速幂-模板)
分析:求Map^k,刚开始没有用快速幂,TLE了 代码如下: =================================================================== ...
- + (void)load和+ (void)initialize有什么用处
两个方法都可以进行一些类的初始化操作.其中有些小区别.+(void)load 方法只要加入了工程种,进行了编译,且.m中实现了这个方法,都会调用一次,值得注意的时没实现的子类是不会调用的,就算父类实现 ...
- OpengGL ES2.0 Using NDK
使用C语言在Android Studio中编写OpenGL ES,首要的任务就是配置编程环境. 在最新的Android Studio中,可以直接编译C/C++源代码.本人的版本是Android Stu ...