Java 中 hashCode 和 equals 方法 小结

转载:http://www.oschina.net/question/82993_75533

hashCode()和equals()定义在Object类中,这个类是所有java类的基类,所以所有的java类都继承这两个方法。

hashcode主要是set集合使用,是用于判断对象是否”可能“相等的快捷办法,以解决大集合的问题。举例来说,如果一个一万个元素的集合加入一个元素,如果是一个新元素,那么必须要equal一万次才能加入。所以采用hashcode,hashcode的思路是如果equal,则hashcode一定要相等,反过来则不一定;所以如果hashcode不相等,那么一定不equal,这跟md5的hash来判别密码是一个道理。hashcode用64位整数,这样可以建立一个索引,新加入元素,先判断这个新元素的hashcode是否存在,如果不存在,肯定不相等,加入set中;如果存在,则与已有的hashcode的若干个元素比较,这样大大简化了set的equal操作。

使用hashCode()和equals()

hashCode()方法被用来获取给定对象的唯一整数。这个整数被用来确定对象被存储在HashTable类似的结构中的位置。默认的,Object类的hashCode()方法返回这个对象存储的内存地址的编号。

重写默认的实现

如果你不重写这两个方法,将几乎不遇到任何问题,但是有的时候程序要求我们必须改变一些对象的默认实现。

来看看这个例子,让我们创建一个简单的类Employee


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

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类只是有一些非常基础的属性和getter、setter.现在来考虑一个你需要比较两个employee的情形。


1

2

3

4

5

6

7

8

9

10

11

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,但是,事实上上面两个对象代表的是通过一个employee。真正的商业逻辑希望我们返回true。 
为了达到这个目的,我们需要重写equals方法。


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

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

}

在上面的类中添加这个方法,EauqlsTest将会输出true。 
So are we done?没有,让我们换一种测试方法来看看。


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

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

    }

上面的程序输出的结果是两个。如果两个employee对象equals返回true,Set中应该只存储一个对象才对,问题在哪里呢? 
我们忘掉了第二个重要的方法hashCode()。就像JDK的Javadoc中所说的一样,如果重写equals()方法必须要重写hashCode()方法。我们加上下面这个方法,程序将执行正确。

(大概意思是说31这个值是一个奇素数,只是一个默认的传统。并不一定要用31。但是这个数可以通过位移的方式来处理乘法,获得一些性能上的优化。虚拟机会自动做这些优化。)


1

2

3

4

5

6

7

8

@Override

 public int hashCode()

 {

    final int PRIME = 31;

    int result = 1;

    result = PRIME * result + getId();

    return result;

 }

hash散列算法,使得在hash表中查找一个记录速度变O(1). 每个记录都有自己的hashcode,散列算法按照hashcode把记录放置在合适的位置. 在查找一个记录,首先先通过hashcode快速定位记录的位置.然后再通过equals来比较是否相等. 没有hashcode,一个一个比较过来,时间就变O(N)了.

hashCode()方法要求:

当对象状态未改变,那么多次调用返回的值必须相等
两个对象equal,那么对象调用返回的值必须相等

equals方法的使用者是我们,而hashcode方法是jdk(如往list中插入值,会根据code决定顺序,这是equals方法无法代替的)。整体来说,equals相等,那么hashcode必须一样。而hashcode一样,equals不一定一样。

如果两个对象==,那么一定equal,然后一定要hashcode相等。而默认的实现是三个方法都采用了比较地址的方法,也就是三个其实都是等价的。所以,改写了equal,扩大了equal的情况范围,那么必须要同步扩大hashcode的相等范围,以维持”==则equal,equal则hashcode相等“的逻辑。

==是指的同一个的对象的2个不同的引用比较,在内存中指的是同一个地址。

时间: 2024-10-25 15:15:59

Java 中 hashCode 和 equals 方法 小结的相关文章

面试点:Java 中 hashCode() 和 equals() 的关系

Java 中 hashCode() 和 equals() 的关系是面试中的常考点,如果没有深入思考过两者设计的初衷,这个问题将很难回答.除了应付面试,理解二者的关系更有助于我们写出高质量且准确的代码. 一.基础:hashCode() 和 equals() 简介 在学习 hashCode() 和 equals() 之间的关系之前, 我们有必要先单独地了解他俩的特点. equals() equals() 方法用于比较两个对象是否相等,它与 == 相等比较符有着本质的不同. 在万物皆对象的 Java

java的Object类中hashCode()和equals()方法-----转载

JAVA代码:    public static void main(String[] args)    {        Object obj1 = new Object();        Object obj2= new Object();        Object obj3 = obj2;        System.out.println("obj1==obj2 ?"+obj1.equals(obj2));        System.out.println("o

Java中的==和equals方法详解

Java中的==和equals   1.如果比较对象是值变量:只用== 2.如果比较对象是引用型变量: ==:比较两个引用是不是指向同一个对象实例. equals: 首先Object类中equals的实现是直接调用了==操作. 一个自定义类继承自Object且没有重写equals方法,那么其equals操作也是与Object类一样,仅仅是直接调用==操作. 如果一个类重写过equals方法(或者继承自一个重写过equals方法的类),那么效果与==操作不同 如果是你自己定义的一个类,比较自定义类

java中hashcode()和equals()的详解

今天下午研究了半天hashcode()和equals()方法,终于有了一点点的明白,写下来与大家分享(zhaoxudong 2008.10.23晚21.36). 1. 首先equals()和hashcode()这两个方法都是从object类中继承过来的. equals()方法在object类中定义如下: public boolean equals(Object obj) { return (this == obj); } 很明显是对两个对象的地址值进行的比较(即比较引用是否相同).但是我们必需清

java 中hashcode和equals 总结

一.概述            在Java中hashCode的实现总是伴随着equals,他们是紧密配合的,你要是自己设计了其中一个,就要设计另外一个.当然在多数情况下,这两个方法是不用我们考虑的,直接使用默认方法就可以帮助我们解决很多问题.但是在有些情况,我们必须要自己动手来实现它,才能确保程序更好的运作. 1.1 规则 粗略总结一下在JavaDoc中所规定hashcode方法的合约:      Objects that are equal must have the same hash co

[转载]Java中hashCode与equal方法详解

转载自http://blog.csdn.net/jiangwei0910410003/article/details/22739953 Java中的equals方法和hashCode方法是Object中的,所以每个对象都是有这两个方法的,有时候我们需要实现特定需求,可能要重写这两个方法,今天就来介绍一些这两个方法的作用. equals()和hashCode()方法是用来在同一类中做比较用的,尤其是在容器里如set存放同一类对象时用来判断放入的对象是否重复. 这里我们首先要明白一个问题: equa

java中hashcode()和equals()的详解 (转)

(zhaoxudong 2008.10.23晚21.36). 1. 首先equals()和hashcode()这两个方法都是从object类中继承过来的. equals()方法在object类中定义如下:   public boolean equals(Object obj) { return (this == obj); } 很明显是对两个对象的地址值进行的比较(即比较引用是否相同).但是我们必需清楚,当String .Math.还有Integer.Double....等这些封装类在使用equ

从语言设计的角度探究Java中hashCode()和equals()的关系

目录 一. 基础: hashCode()和equals()简介 二. 漫谈: 引入hashCode()与equals()之间的关系 三. 解密: 深入理解hashCode()和equals()之间的关系. 四. 验证: 结合HashMap的源码和官方文档, 验证两者的关系. 一. 基础: hashCode()和equals()简介 在学习hashCode()和equals()之间的关系之前, 我们有必要先单独了解他俩自身的特点. equals()方法用于比较两个对象是否相等, 它与"==&quo

Java 中的== 和equals()方法

Java中的数据类型,可分为两类: 1.基本数据类型,也称原始数据类型.byte,short,char,int,long,float,double,boolean 他们之间的比较,应用双等号(==),比较的是他们的值. 2.引用数据类型(类) 当它们用(==)进行比较的时候,比较的是他们在内存中的存放地址,所以,除非是同一个new出来的对象,他们的比较后的结果为true,否则比较后结果为false. Java当中所有的类都是继承于Object这个基类的,在Object中的基类中定义了一个equa