在这篇文章中,我将指出我对hashCode()和equals()方法的理解。我将讨论它们的默认实现以及如何正确地覆盖它们。我还将使用Apache Commons包中的实用工具类来实现这些方法。

hashCode()和equals()方法已经在Object类中定义,而Object类是所有Java对象的父类。因为这个原因,所有的Java对象从Object类继承了这些方法的默认实现。

本文中的章节:

  hashCode()和equals()用法

  重写默认行为

  用Apache Commons Lang重写equals()和hashCode()

  需要记住的重要的事项

  在ORM中使用时要注意的地方

hashCode()equals()方法的用法

hashCode()方法用于获取给定对象的唯一的整数。当这个对象需要存储在哈希表这样的数据结构时,这个整数用于确定桶的位置。默认情况下,对象的hashCode()方法返回对象所在内存地址的整数表示。

equals()方法用来简单验证两个对象的相等性。默认实现只检查两个对象的对象引用,以验证它们的相等性。

 

重写默认行为

通常情况下,类一切运行的都很好,根本不需要重写它们,但是有时应用程序需要更改某些对象的默认行为。

让我们举一个例子,比如有一个应用程序拥有员工对象。让我们创建一个尽可能简单的员工类:

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;
}
}

上面的员工类有一些非常基本的属性和访问方法。现在考虑一个简单的情况,您需要比较两个员工对象。

public class EqualsTest {
public static void main(String[] args) {
Employee e1 = new Employee();
Employee e2 = new Employee(); e1.setId(100);
e2.setId(100); //Prints false in console
System.out.println(e1.equals(e2));
}
}

不用猜,以上方法将输出“false”。但是,这两个对象现实生活中代表同一雇员。在实际应用程序中,必须返回true。

要实现正确的行为,我们需要如下重载equal方法:

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()); }

把这个方法添加到你的员工,开始运行EqualTest,将打印true。

这就完了吗?还没有。让我们以不同的方式再次测试上面修改过的员工类。

import Java.util.HashSet;
import Java.util.Set; 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<Employee>();
employees.add(e1);
employees.add(e2); //Prints two objects
System.out.println(employees);
}
}

上面的类在第二个打印语句中打印两个对象。如果员工对象已经相等,在一个Set集合中应该只存在一个对象, HashSet中该只有一个实例才对,毕竟对象指的是同一名员工。哪里出现了问题??

问题出现在我们没有重写第二个重要的方法hashCode()。Java文档说,如果重写equals()方法,然后你必须重写hashCode()方法。因此,让我们在员工类中添加另一个方法。

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

一旦在雇员类中添加了上述方法,第二个语句就开始在第二个语句中只打印单个对象,从而验证了e1和e2的真正相等性。

Apache Commons Lang 重写equals()hashCode()

Apache Commons提供两个优秀的实用类 HashCodeBuilderEqualsBuilder用于生成hashCode和测试相等性的代码。下面是它们的使用:

import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.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 int hashCode()
{
final int PRIME = 31;
return new HashCodeBuilder(getId()%2==0?getId()+1:getId(), PRIME).toHashCode();
}
@Override
public boolean equals(Object o) {
if (o == null)
return false; if (o == this)
return true; if (o.getClass() != getClass())
return false; Employee e = (Employee) o; return new EqualsBuilder().
append(getId(), e.getId()).
isEquals();
}
}

或者,用代码编辑器自动生成,它们必然能够为您生成一些良好的代码。例如,Eclipse IDE选项, 在类上右键 >> source > Generate hashCode() and equals() … 会为你生成一个很好的实现。

需要记住的重要事项

1) 始终使用一个对象的相同属性来生成hashCode()和equals()方法。在我们的例子中,我们使用了员工id。

2) equals()必须一致(如果对象不被修改,那么它必须返回相同的值)。

3) 每当a.equals(b),那么a.hashCode()和b. hashCode()必须相等。

4) 如果重写一个,则应重写另一个。

ORM中使用时需要注意的地方

如果你正在处理一个ORM,确保hashCode()和equals()中始终使用getters,不要直接使用字段。这是因为在ORM中,偶尔字段被延迟加载,直到调用它们的getter方法时才可用。

例如我们的员工类,如果我们使用e1.id = = e2.id。id字段非常可能是懒加载。因此,在这种情况下,一个可能是零或null,从而导致不正确的行为。

但如果采用e1.getid() == e2.getid(),我们可以肯定,即使是懒加载,调用getter将首先让字段加载正确。

这就是我关于hashCode()和equals()方法所知道的,希望它会帮助有的人。

如果你觉得,我遗漏了什么或错误的地方,请留下评论。我会再次更新这篇文章来帮助别人。

Happy Learning !!

使用hashCode()和equals()方法 - Java的更多相关文章

  1. Java 中正确使用 hashCode 和 equals 方法

    在这篇文章中,我将告诉大家我对hashCode和equals方法的理解.我将讨论他们的默认实现,以及如何正确的重写他们.我也将使用Apache Commons提供的工具包做一个实现. 目录: hash ...

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

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

  3. (转)Java 中正确使用 hashCode 和 equals 方法

    背景:最近在编写持久化对象时候遇到重写equals和hashCode方法的情况,对这两个方法的重写做一个总结. 链接:https://www.oschina.net/question/82993_75 ...

  4. 重写Java Object对象的hashCode和equals方法实现集合元素按内容判重

    Java API提供的集合框架中Set接口下的集合对象默认是不能存储重复对象的,这里的重复判定是按照对象实例句柄的地址来判定的,地址相同则判定为重复,地址不同不管内容如何都判定为不重复,这有时与需求不 ...

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

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

  6. Java中Set的contains()方法——hashCode与equals方法的约定及重写原则

    转自:http://blog.csdn.net/renfufei/article/details/14163329 翻译人员: 铁锚 翻译时间: 2013年11月5日 原文链接: Java hashC ...

  7. Java中正确使用hashCode和equals方法

    在这篇文章中,我将告诉大家我对hashCode和equals方法的理解.我将讨论他们的默认实现,以及如何正确的重写他们.我也将使用Apache Commons提供的工具包做一个实现. 目录: hash ...

  8. Java 重写 hashCode() 和 equals() 方法

    1. hashCode 1.1 基本概念 hashCode 是 JDK 根据对象的地址算出来的一个 int 数字(对象的哈希码值),代表了该对象再内存中的存储位置. hashCode() 方法是超级类 ...

  9. 为什么要重写hashcode和equals方法?初级程序员在面试中很少能说清楚。

    我在面试 Java初级开发的时候,经常会问:你有没有重写过hashcode方法?不少候选人直接说没写过.我就想,或许真的没写过,于是就再通过一个问题确认:你在用HashMap的时候,键(Key)部分, ...

随机推荐

  1. mui开发app之自定义事件以更新其他页内容

    我之前做过jquery mobile的开发,那还是前年的事情 在jquery mobile中,由于页面是存储在div[data-role=page]的dom中(jqmobile通过对data-role ...

  2. JAVA中令人疑惑的字符串

    Java中不同的字符串存在于同一个存储池中,字符串变量将指向存储池中相应的位置,也就是字符串变量里面包含的并不是字符串而是这个字符串对象的内存地址. String a = "123" ...

  3. poj3020二分图匹配

    The Global Aerial Research Centre has been allotted the task of building the fifth generation of mob ...

  4. Hadoop集群

    你可以用以下三种支持的模式中的一种启动Hadoop集群: 单机模式 伪分布式模式 完全分布式模式 单机模式的操作方法 默认情况下,Hadoop被配置成以非分布式模式运行的一个独立Java进程.这对调试 ...

  5. jquery按钮绑定特殊事件

    本文主要介绍点击一个按钮处理事件的一些特殊情况和技巧. 一.第一次点击触发一个函数,之后点击都触发另一个函数 1.小白实现 2.大神实现 代码如下: <body> <button&g ...

  6. 案例分享|某医药集团的BI建设案例

    相比于传统型BI,越来越多的企业开始接受并青睐新型的自助式BI,因其项目上线快,失败风险小,简单易用,颇受赞誉.以下是某医药集团上线帆软BI系统FineBI的案例,从用途架构.指标分析.和信息交互几方 ...

  7. 前端 tips

    1.==和!=操作符会在需要的情况下自动转换数据类型.但===和!==不会,它们会同时比较值和数据类型,这也使得它们要比==和!=快. 2.首次为变量赋值时务必使用var关键字,变量没有声明而直接赋值 ...

  8. SSH协议(转载)

    一. SSH是什么? SSH的全称是Secure Shell, 是一种"用来在不安全的网络上安全地运行网络服务的一种加密网络协议". 简单说,SSH是一种网络协议,用于计算机之间的 ...

  9. Welcome to my Blog

    Only English? Oh my god!!! why open live write can't write by Chinese?

  10. HDU1829(种类并查集)

    ps:本来是想找个二分图判断的题来写,结果百度到这鬼题 Problem Description Background Professor Hopper is researching the sexua ...