`

关于重写类的hashcode和equals方法的注意点

    博客分类:
  • j2se
 
阅读更多

首先们先打个比方 现在有一个集合HashSet 这个集合里放的是一个Person类的实例对象 这个Person类重写了hashcode和equals方法

Person类的代码如下:

@Override
public boolean equals(Object obj) {
  // TODO Auto-generated method stub
  if(this==obj){
   return true;
  }
  if(obj instanceof Person){
   Person person = (Person)obj;
   if(this.name.equals(person.getName()) && (this.age==person.getAge())){
    return true;
   }else{
    return false;
   }
  }
  return false;
}
@Override
public int hashCode() {
  // TODO Auto-generated method stub
  return this.name.hashCode()*30+this.age*23;
}

 

我们重写的hashcode方法中Person属性的name和age参与了hashcode得计算

下面我向set集合里添加几个Person类的实例对象

Set<Person> persons = new HashSet<Person>();
  Person person1 = new Person("cdx",23);
  Person person2 = new Person("cdx1",24);
  Person person3 = new Person("cdx2",25);
  Person person4 = new Person("cdx",23);
  persons.add(person1);
  persons.add(person2);
  persons.add(person3);
  persons.add(person4);
  persons.add(person1);
  //应该是3 三个元素因该是person1 person2 person3
  //当我们放person4时会判断equals和后hashcode和peson1都相同就不会再向里加了
  //而不是把以前的给覆盖了
  System.out.println(persons.size());
  //现在我来改变person1的age值然后移除person1 来看看我们能不能移除person1
  person1.setAge(21);
  persons.remove(person1);
  //打印出来是3
  System.out.println(persons.size());

 当我们对类的属性参与hashcode运算时我们不能再随意修改参与运算的参数的值了 因为当我们在向set中放置person时 java虚拟机会根据每个对象的计算出的hashcode值来判断把对象放置在内存hash的哪个区域 当我们放进去之后我们去修改某个参与hashcode计算的属性的值时 这个person1的hashcode的就会改变 当我们去移除他的时候 会根据改变后的hashcode值去hash的某个区域去寻找对象然后移除 但是这时因为hashcode值被改变 所以在hash区域里根本找不到对应的hash值 所以以前的对象根本没有移除掉

 

 

在重写任何类的equals方法是必须遵循以下几点:

1、对称性:如果x.equals(y)返回是“true”,那么y.equals(x)也应该返回是“true”。

2、反射性:x.equals(x)必须返回是“true”。

3、类推性:如果x.equals(y)返回是“true”,而且y.equals(z)返回是“true”,那么z.equals(x)也应该返回是“true”。 

4、还有一致性:如果x.equals(y)返回是“true”,只要x和y内容一直不变,不管你重复x.equals(y)多少次,返回都是“true”。

5、任何情况下,x.equals(null),永远返回是“false”; 

 

 

在重写任何类得hashcode方法是必须遵循以下几点:

1、在Java应用的同一次执行过程中,同一对象被多次调用,则他们的hashcode值必然相同。而对于同一个应用的两次不同的调用,它们的Hashcode值可以相同,也有可能不同。

2、对于两个对象来说,如果他们的equals方法比较返回true,那么这两个对象的hashcode必然相同。这也解释了为什么String类中,如果两个对象的equals方法相同,则他们的hashcode值一定相同。

3、对于两个对象来说,如果使用equals方法返回为false,则他们的hashcode的值有可能相等也可能不等,(如果不同会提高性能,因为在集合中类判断两个对象是否相等,如果其hashcode不等就直接不用判断equals方法了)

4、对于Object对象来说,不同的Object对象的hashcode是不同的,它们返回的是对象的地址,equals返回的也是对象的地址。所以在自己定义的类中如果要添加到集合对象中,最好是要重写hashcode和equals方法,不然会自动继承自Object类中的两个方法根据对象地址来判断。在重写自己定义的类时,通常是在类中的根据某个值如name.hashcode();来进行判断。

以HashSet 为例,

 

当我们使用HashSet时,hashCode()方法就会被得到调用,判断已经存储在集合中的对象的hashCode值是否与所增加

 

对象的hashCode值一致,如果“不一致”则直接加进去(不用比较equals()提高效率),如果一致,则进行equals方法的比较,如果返回true,表明
集合里面已经有这个对象,不能添加进去了。如果是false表是集合里面没有这个对象,则可以加进去。所以我们在重写hashcode()或者equals()
方法的任何一个方法时,必须重写另外一个。
自己手工写了一个类来重写这两个方法:
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
/**
 *
 * People  手工重写hashcode方法和equals方法  根据name来判断 两个对象是否相等。
 * 2011-7-12 上午09:09:56
 *
 * @version 1.0.0
 *
 */
class People {
	private String name;
 
	public People(String name){
		this.name=name;
	}
	@Override
	public boolean equals(Object obj) {
 
		// TODO Auto-generated method stub
		//如果是自己
		if(this==obj){
			return true ;
 
		}
		//如果是空
		if(obj==null ){
			return false;
		}
		//比较两个People的名字是否相同
		if(obj!=null && obj instanceof People){
			if(((People)obj).name.equals(this.name))
				return  true ;
 
		}
		return false;
 
	}
 
	@Override
	public int hashCode() {
 
		// TODO Auto-generated method stub
		//String的hashcode本来就是用来比较两个字符是否相等
		return  name.hashCode();
 
	}
 
}

其他相关问题:

       那么在String中的hashcode是怎么定义的呢?在String的API中我们可以看到这样一个公式: s[0]*31^(n-1) + s[1]*31^(n-2) + … + s[n-1] 使用int 算法,这里s[i] 是字符串的第i 个字符,n 是字符串的长度,^ 表示求幂。(空字符串的哈希码为0。)这说明String 中的hashcode 返回的并不是在内存中的地址,如果两个字符串的内容相同(equals为true),则其hashcode值必然就相同,equal为true。同理经过傻蛋测试在Integer类中和String类似,hashcode方法和equals方法也是判断其包裹的原始值的内容是否相同。

总结:在Java中,String 、Math、还有Integer、Double。。。。等这些封装类重写了Object中的equals()方法,让它不再比较其对象在内存中的地址,而是比较对象中实际包含的整数的值,即比较的是内容。再强调一次,Object的equals()方法比较的是地址值,所以Object equals相等时,其hashcode必然相等,因为都是对象的地址,所以自己定义的类如果要加入到集合类中一定要记得重写这两个方法。

      在Eclipse中重写hashcode和equals方法使相当方便的,只需要右键->source->Generate hashcode() and equals()便可以了。

分享到:
评论

相关推荐

    重写equals和hashcode方法_equals_重写equals和hashcode方法_

    在Java编程语言中,`equals()` 和 `hashCode()` 方法是Object类中的两个核心方法,所有类都默认继承自Object类。这两个方法在处理对象比较和集合操作时起着至关重要的作用。当我们创建自定义类并需要对对象进行精确...

    Java重写equals同时需要重写hashCode的代码说明

    Java重写equals同时需要重写hashCode的代码说明,以及如何重写hashCode方法,此代码演示按照effective java书籍说明的重写思路。代码中演示了使用集合存储对象,并且对象作为key,需重写equals和hashCode.

    重写hashCode()和equals()方法详细介绍

    在Java编程中,`equals()` 和 `hashCode()` 方法是Object类中的两个重要方法,它们在处理对象相等性以及在哈希表(如HashSet、HashMap)中起到关键作用。当自定义类时,有时需要根据业务逻辑重写这两个方法以满足...

    关于重写equals,hashcode以及compareTo方法!

    在某些情况下,我们需要重写hashcode()方法,使其生成对象的哈希码,并且使其与equals()方法保持一致。 例如,在Hashtable、HashMap、HashSet、LinkedHashMap等容器中,我们需要重写hashcode()方法,使其生成对象的...

    Java_重写equals()和hashCode()

    当同时重写 `equals()` 和 `hashCode()` 时,需要注意的一点是,如果 `equals()` 返回true,那么两个对象的 `hashCode()` 必须相等。反之则不一定,因为不同的对象可能会产生相同的哈希码。这就是为什么在设计类时,...

    java中hashcode和equals的详解.pdf

    equals 方法是 Java 中一个非常重要的方法,因为它是 Object 类中的一个基本方法,每个对象都可以根据自己的需求来重写这个方法。 三、hashCode 和 equals 方法的关系 hashCode 和 equals 方法之间存在着紧密的...

    关于hashCode()和equals()的本质区别和联系

    本文将详细介绍 hashCode() 和 equals() 的本质区别和联系,并探讨在创建 Java 类时如何定义这些方法。 hashCode() 方法 hashCode() 方法是 Object 类中的一个方法,它返回对象的哈希码值。哈希码值是一个整数,它...

    重写equals方法

    第一种情况:如果类中提供的 equals 方法无法满足需求,则需要重写 equals 方法。例如,在 String 类中,equals 方法用于比较两个字符串的内容是否相同,而不是比较它们的引用。 第二种情况:对于采用哈希算法的...

    hashcode和equals的分析

    ### hashCode和equals方法详解 #### 一、hashCode方法解析 在深入探讨`hashCode`方法之前,我们需要了解Java集合框架的基本概念。Java集合框架主要包括两大类集合:`List`和`Set`。 - **List**:这是一个有序集合...

    HashCode相同equals不同的2位字符集合算法

    在实际编程中,通常推荐使用`Objects`类的`equals()`和`hashCode()`方法,它们提供了安全且一致的实现。例如: ```java public class TwoCharSet { private char char1; private char char2; // 构造器、...

    Java中hashCode和equals方法的正确使用

     hashCode()和equals()定义在Object类中,这个类是所有java类的基类,所以所有的java类都继承这两个方法。  使用hashCode()和equals()  hashCode()方法被用来获取给定对象的整数。这个整数被用来确定对象被...

    【面试】hashCode与equals两者之间的关系 / == 和equals / 为什么要重写equals方法 / 重写equals /hashcode方法 / 为什么要重写hashCode方法

    7、**重写hashCode()方法的注意事项**: 重写`hashCode()`时,应确保它与`equals()`方法的逻辑一致。通常,`hashCode()`应该基于对象的那些参与`equals()`比较的属性来计算。如果两个对象`equals()`相等,它们的`...

    为什么重写equals方法,还必须要重写hashcode方法

    为什么重写equals方法,还必须要重写hashcode方法

    equals与hashCode在实际开发中的重写写法

    在 TestEqualsHashCode.java 文件中,通常会包含一个示例,演示如何正确地重写 `equals()` 和 `hashCode()` 方法。这个文件可能包含一个自定义类,并展示如何根据类的属性定义这两个方法,以实现特定的比较逻辑。 ...

    java中重写equals()方法的同时要重写hashcode()方法(详解)

    在 Java 中,重写 equals() 方法和 hashCode() 方法是非常重要的,它们可以确保对象的比较和标识正确。如果我们违反了这两个方法的规则,那么可能会产生理解的不一致。因此,在编写 Java 代码时,需要严格遵守这两个...

    equals方法的重写.docx

    ### equals方法重写知识点解析 #### 一、equals方法简介 `equals`方法是Java语言中Object类的一个重要成员方法,其默认实现是比较两个对象的内存地址是否相同(即是否为同一个对象)。为了使对象之间能够基于内容...

    java中为何重写equals时必须重写hashCode方法详解

    当我们在自定义类中重写 `equals()` 方法时,通常也需要重写 `hashCode()` 方法,这是为了遵循一些重要的原则和保证数据结构如 `HashMap`、`HashSet` 的正确行为。 首先,`equals()` 方法用于比较两个对象是否相等...

    为什么在重写 equals方法的同时必须重写 hashcode方法

    在 Java 中,`equals` 和 `hashCode` 方法是 Object 类中的两个重要方法,它们用于比较对象的相等性。默认情况下,`equals` 方法比较的是两个对象的引用,即是否指向内存中的同一个位置,而 `hashCode` 方法则返回...

    hashcode()和equals()

    在Java编程语言中,`hashCode()` 和 `equals()` 方法是两个非常重要的概念,尤其是在处理对象比较和哈希表(如 `HashMap` 或 `HashSet`)时。这两个方法来源于 `Object` 类,是所有Java类的基类,因此,每个自定义类...

    关于Object中equals方法和hashCode方法判断的分析

    "关于Object中equals方法和hashCode方法判断的分析" 在 Java 中,Object 类提供了两个重要的方法:equals 方法和 hashCode 方法。这两个方法都是用于比较两个对象是否相等的,但它们的实现机理和作用域却有所不同。...

Global site tag (gtag.js) - Google Analytics