【翻译】玩转Java的hashCode()与equals()方法
来源:互联网 发布:极客帮是什么软件 编辑:程序博客网 时间:2024/06/05 02:18
【翻译】玩转Java的hashCode()
与equals()
方法
hashCode()
与equals()
方法本文将讨论Java中的
hashCode()
和eqauls()
方法的默认实现,如何正确地重写,以及如何使用Apache Commons
包的一些工具类。hashCode()
和eqauls()
方法在Object
类中定义的,因此,所有的Java对象继承了这两个方法的默认实现。一、hashCode()
和eqauls()
方法的使用
hashCode()
方法用来获取给定对象的特定整型值(哈希码)。在像HashMap
类似的数据结果中,这个整数用来确定对象存储在哪个哈希桶(Hash bucket)中。默认情况下,对象的hashCode()
方法返回的这个整型值代表了对象存储的内存地址。 equals()
方法用来判断两个对象是否相等。默认的实现仅简单地检查两个对象的引用地址是否相等。
二、重写默认的行为
如果我们在自定义的类中不重写任何方法,可以确保所有的方法运行正常。但是,在应用软件中经常需要去改变一些对象的默认行为。让我们来看一个包括Employee
类的代码实例。首先,让我们来创建一个Employee
类:
public class Employee { private Integer id; private String firstname; private String lastname; private String department; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getFirstname() { return firstname; } public void setFirstname(String firstname) { this.firstname = firstname; } public String getLastname() { return lastname; } public void setLastname(String lastname) { this.lastname = lastname; } public String getDepartment() { return department; } public void setDepartment(String department) { this.department = department; }}
上面的Employee
类封闭了一些基本的属性及其访问方法。现在,我们来考虑一个简单的场景,即,我们需要判断两个Employee
对象是否相等。
public class EqualsTest { public static void main(String[] args) { Employee e1 = new Employee(); Employee e2 = new Employee(); e1.setId(100); e2.setId(100); System.out.println(e1.equals(e2)); }}
上述代码将返回“false”。但是从实际情况来看,这两个对象代表的其实是同一个employee,因此,在我们的应用中应该返回true。
为了实现上述的行为,我们需要按如下的方式重写equals()
方法:
@Override public boolean equals(Object o) { if(o == null){ return false; } if(o == this){ return true; } if(o instanceof Employee){ Employee e = (Employee) o; return (this.getId() == e.getId()); } return false; } @Override public String toString() { // TODO Auto-generated method stub return "Employee:[id: "+this.getId() + "]"; }
将上述方法添加到Employee
类后,EqualsTest
将返回true。
到此,我们就完成了所有工作了吗?当然不是。让我们用不同的方法来对测试一下修改后的Employee
类。
public class EqualsTest { public static void main(String[] args) { Employee e1 = new Employee(); Employee e2 = new Employee(); e1.setId(100); e2.setId(100); //Prints 'true' System.out.println(e1.equals(e2)); Set<Employee> employees = new HashSet<>(); employees.add(e1); employees.add(e2); //Prints two objects. System.out.println(employees); }}
输出结果:
true[Employee:[id: 100], Employee:[id: 100]]
上述代码打印HashSet
对象employees
时打印了两个。如果两个employees
对象相等,那么Set
中应该只保存一个对象。什么地方出错了呢?
我们还需要重写另一个重要的方法hashCode()
。如Java Docs中所描述的,如果我们重写equals()
方法,那么我们必须同时重写hashCode()
方法。因此,让我们在Employee
类中添加另一个方法。
@Override public int hashCode() { // TODO Auto-generated method stub final int PRIME = 31; int result = 1; result = PRIME * result + getId().hashCode(); return result; }
执行EqualsTest
,输出结果:
true[Employee:[id: 100]]
当我们在Employee
类中添加了上述方法,EqualsTest````HashSet
对象employees
时仅打印了一个对象,从而证明e1与e2相等性。
三、使用Apache Commons Lang
重写hashCode()
和equals()
方法
Apache Commons
提供了两个非常优化的工具类HashCodeBuilder
和EqualsBuilder
,用来生成hashCode()
和equals()
方法。下面是其使用方法:
import org.apache.commons.lang.builder.EqualsBuilder;import org.apache.commons.lang.builder.HashCodeBuilder;public class Employee { private Integer id; private String firstname; private String lastname; private String department; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getFirstname() { return firstname; } public void setFirstname(String firstname) { this.firstname = firstname; } public String getLastname() { return lastname; } public void setLastname(String lastname) { this.lastname = lastname; } public String getDepartment() { return department; } public void setDepartment(String department) { this.department = department; } @Override public boolean equals(Object o) { if(o == null){ return false; } if(o == this){ return true; } if(o instanceof Employee){ Employee e = (Employee) o; return new EqualsBuilder().append(getId(), e.getId()).isEquals(); } return false; } @Override public int hashCode() { final int PRIME = 31; return new HashCodeBuilder(getId() % 2 == 0 ? getId() + 1 : getId(), PRIME).toHashCode(); } @Override public String toString() { // TODO Auto-generated method stub return "Employee:[id: "+this.getId() + "]"; }}
此外,如果我们使用集成开发环境(IDE),我们也可以利用IDE来自动生成一个结构良好的代码。例如:在Eclipse IDE中可以右击**class>>source>>Generate hashCode() and equals()…,就可以为我们生成实现良好的代码。
四、需要记住的关键点
- 通常需要使用同一个属性来生成
hashCode()
和equals()
方法。在上面的示例中,我们使用的是Employee id
。 - 需要保证
equals()
方法返回值的一致性。即,如果对象没有被修改,那么,多次调用equals()
方法比较时返回同样的值。 - 当
a.equals(b)
返回true
时,a.hashCode()
与b.hashCode()
必须相等。 - 如果我们重写了
equals()
和hashCode()
两个方法中的任意一个,则必须重写另一个。
五、在ORM
中使用的特殊点
**Info: **ORM,Object Relation Mapping,对象关系映射,用于实现面向对象编程语言里不同类型系统的数据之间的转换。
我们在处理对象关系映射时,在hashCode()
和equals()
方法中需要确保访问对象属性时使用getters
,而不是使用属性引用。因为,在对象关系映射的处理中,有时会使用迟延加载来实例化属性,对象属性直到调用getter
方法时才可用。
- 【翻译】玩转Java的hashCode()与equals()方法
- Java的equals方法与hashcode
- java equals与hashCode方法
- Java equals()与hashCode()方法
- java中hashCode方法与equals方法的用法总结
- java中hashCode方法与equals方法的用法总结
- java中hashCode方法与equals方法的用法
- java中hashCode方法与equals方法的用法总结
- java中hashCode方法与equals方法的用法总结
- java中hashCode方法与equals方法的用法总结
- java中hashCode方法与equals方法的用法总结
- java中hashCode方法与equals方法
- java equals与hashCode 两个重要方法的重写
- java中hashcode与equals方法的作用
- java中equals与hashcode的方法使用
- java中hashcode与equals方法
- Java中equals()与hashCode()方法详解
- java 集合中hashcode与equals方法
- 线程安全与非安全
- opencv simpleBlobDetector入坑
- Pixhawk学习笔记(4)——PX4FLOW
- Tcp文件上传
- Windows下编译fast rcnn 遇到的问题
- 【翻译】玩转Java的hashCode()与equals()方法
- 设置MySQL最大连接数
- linux环境下时间的创建与修改
- C++长字符串换行
- java 中 equals()和hashCode()的关系
- 【mybatis深度历险系列】mybatis中的动态sql
- apk下载提示404错误
- English in August
- 断点续传