在Java语言中,Object对象中包含一个equals和hashCode方法,其中hashCode方法是由JVM本地代码(native code)实现的,返回值是一个有符号的32位整数,对象的hash值一般为用于在管理多个对象的数据结构中用于提高性能而设计的,比如HashMap。有些语言的hash值就是这个对象在内存中的地址转化的整数,但是java中的实现并不是这样。equals方法的实现很简单,就是利用==运算符比较两个对象的内存引用地址是否相等,当然,不是所有对象的比较都是比较内存,比如Integer,Long,Double等这些表示数字的类内部都对equals方法进行了重写,这些数值类equals比较的是数值大小。
 
Object类的equals&hashCode的实现:
public boolean equals(Object obj) {
return (this == obj);
} public native int hashCode();
Integer类的内部equals和hashCode的实现:
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
} public int hashCode () {
return value;
}

关于hash值的一般性规约

  • 对同一个对象多次调用hashCode方法,都应该始终如一的返回同一个值
  • 对象相等,其hash值比较也应该相等(如果重写了对象的equals方法,那么对应的hashCode的实现也应该要重写以保证hash值也是相等的)
  • 对象不等,其hash值不要求也不等(但如果能不等,会提高程序性能)。
重写HashCode()和equals()
 
Employee e1 = new Employee();
Employee e2 = new Employee(); e1.setId(100);
e2.setId(100);
//Prints false in console
System.out.println(e1.equals(e2)); // output: false
对于上面的代码,在具体的业务逻辑中我们通常希望比较的结果应该是:true,但是由于两个对象引用的地址不同,所以equals比较的结果是false,若希望e1和e2比较的结果是true,我们就需要重写equals方法
@override
public boolean equals(object o) { if(o == null) { return false;
}
if (o == this)
{
return true;
}
if (getClass() != o.getClass())
{
return false;
}
Employee e = (Employee) o;
return (this.getId() == e.getId());
}

再看下面的例子:

Set<Employee> employees = new HashSet<Employee>();
employees.add(e1);
employees.add(e2);
System.out.println(employees); // output: two elements

我们期望的结果是:若equals比较相等的对象,放入HashSet或HashMap中也应该只能放入一个,但为什么会出现两个元素呢,因为两个对象的hashCode值是不一样的,所以HashSet认为是两个不同的元素。因此,若想得到期望的结果,需要重写hashCode方法:

 
@Override
public int hashCode()
{
final int PRIME = 31;
int result = 1;
result = PRIME * result + getId();
return result;
}

利用Eclipse的代码生成工具生成重写HashCode和equals的方法

 
生成的代码如下:
@Override
public int hashCode() {
final int prime = 31; // 见参考文章
int result = 1;
result = prime * result + age ;
result = prime * result + (( name == null ) ? 0 : name .hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true ;
if (obj == null)
return false ;
if (getClass() != obj.getClass())
return false ;
HashCodeDemo1 other = (HashCodeDemo1) obj;
if (age != other. age)
return false ;
if (name == null) {
if (other.name != null)
return false ;
} else if (! name.equals(other. name ))
return false ;
return true ;
}

注意事项:

  • equals和hashCode方法一般需要同时重写
  • 如果a.equals(b),那么也要保证a.hashCode() == b.hashCode()
  • 尽量使用相同的属性来重写equals和hashCode方法,比如上述例子中两个重写方法中都是利用的id属性。
  • 如果你使用ORM处理一些对象的话,你要确保在hashCode()和equals()对象中使用getter和setter而不是直接引用成员变量。因为在ORM中有的时候成员变量会被延时加载,这些变量只有当getter方法被调用的时候才真正可用。
参考:

Java中equals,hashcode的更多相关文章

  1. java中“”==“” equals hashcode的关系

    ava中的数据类型,可分为两类: 1.基本数据类型,也称原始数据类型.byte,short,char,int,long,float,double,boolean 他们之间的比较,应用双等号(==),比 ...

  2. K:java中的hashCode和equals方法

      hashCode和equals方法是Object类的相关方法,而所有的类都是直接或间接的继承于Object类而存在的,为此,所有的类中都存在着hashCode和equals.通过翻看Object类 ...

  3. 关于java中的hashcode和equals方法原理

    关于java中的hashcode和equals方法原理 1.介绍 java编程思想和很多资料都会对自定义javabean要求必须重写hashcode和equals方法,但并没有清晰给出为何重写此两个方 ...

  4. java中equals和hashCode方法随笔二

    前几天看了篇关于java中equals和hashCode方法的解析 1.Object类中的equals方法和hashCode方法. Object类中的equals和hashCode方法简单明了,所有的 ...

  5. 浅谈Java中的hashcode方法以及equals方法

    哈希表这个数据结构想必大多数人都不陌生,而且在很多地方都会利用到hash表来提高查找效率.在Java的Object类中有一个方法: public native int hashCode(); 根据这个 ...

  6. Java中equals和hashcode的区别?

    Java中equals和hashcode方法是在Object对象中的,所以每个对象都有这两个方法,大多数时候我们为了实现特定需求需要重写这两个方法 equals和hashcode方法常用在同一个类中用 ...

  7. 浅谈Java中的hashcode方法

    哈希表这个数据结构想必大多数人都不陌生,而且在很多地方都会利用到hash表来提高查找效率.在Java的Object类中有一个方法: 1 public native int hashCode(); 根据 ...

  8. java中的hashcode

    hashcode的作用 对于包含容器类型的程序设计语言来说,基本上都会涉及到hashCode.在Java中也一样,hashCode方法的主要作用是为了配合基于散列的集合一起正常运行,这样的散列集合包括 ...

  9. java中equals和==的区别 (转)

    java中equals和==的区别  值类型是存储在内存中的堆栈(以后简称栈),而引用类型的变量在栈中仅仅是存储引用类型变量的地址,而其本身则存储在堆中. ==操作比较的是两个变量的值是否相等,对于引 ...

  10. 【转】浅谈Java中的hashcode方法(这个demo可以多看看)

    浅谈Java中的hashcode方法 哈希表这个数据结构想必大多数人都不陌生,而且在很多地方都会利用到hash表来提高查找效率.在Java的Object类中有一个方法: public native i ...

随机推荐

  1. phalapi框架where条件查询

    // WHERE name = 'dogstar' AND age = 18 $user->where(array('name' => 'dogstar', 'age' => 18) ...

  2. POJ 2728 Desert King (最优比率树)

    题意:有n个村庄,村庄在不同坐标和海拔,现在要对所有村庄供水,只要两个村庄之间有一条路即可,建造水管距离为坐标之间的欧几里德距离,费用为海拔之差,现在要求方案使得费用与距离的比值最小,很显然,这个题目 ...

  3. day02(继承,重写,this,super,final,抽象类)

    继承 概述:日常生活中儿女总会继承长辈的遗产,java语言也是.通过继承多种实物之间形成一种关系. 特点: ①一个类只能继承一个父类 ②一个父类可以有多个子类 ③可以多层继承(a类继承b类   C类继 ...

  4. HDU1254 推箱子(BFS) 2016-07-24 14:24 86人阅读 评论(0) 收藏

    推箱子 Problem Description 推箱子是一个很经典的游戏.今天我们来玩一个简单版本.在一个M*N的房间里有一个箱子和一个搬运工,搬运工的工作就是把箱子推到指定的位置,注意,搬运工只能推 ...

  5. Quartus II中使用脚本转换sof到rbf文件

    1.  新建一个文本文件,保存为任意但有意义的名字,如:sof_to_rbf.bat,注意,保存时请不要使用默认的格式,应该手动从.txt切换为all files 2.  在文本中输入以下内容: %Q ...

  6. readLine() 和 "\r","\n" 问题

    很多输入流中都有一个函数readLine(),我们也经常使用这个函数,但有时如果不认真考虑,这个函数也会带来一些小麻烦. 如果我们是从控制台读入的话,我们也许没有想过readLine函数到底是根据&q ...

  7. Ansible免密码登陆

    配置Linux主机无密码访问 生成秘钥 ssh-keygen -t rsa Generating public/private rsa key pair. Enter file in which to ...

  8. CSharp程序员学Android开发---1.初识AndriodIDE,掌握工具使用

    最近公司组织项目组成员开发一个Android项目的Demo,之前没有人有Andoid方面的开发经验,都是开发C#的. 虽说项目要求并不是很高,但是对于没有这方面经验的人来说,第一步是最困难的. 项目历 ...

  9. linux新定时器:timefd及相关操作函数

    timerfd是Linux为用户程序提供的一个定时器接口.这个接口基于文件描述符,通过文件描述符的可读事件进行超时通知,所以能够被用于select/poll的应用场景. 一,相关操作函数 #inclu ...

  10. bash基本命令速查表

    来源:https://github.com/skywind3000/awesome-cheatsheets/blob/master/languages/bash.sh ################ ...