`

重写hashCode方法的意义

 
阅读更多

      Java中的很多对象都override了equals方法,都知道,这是为了能比较两个对象是否相等而定义,如果不需要比较,则不需要定义equals方法。比如StringBuffer类,没有提供equals方法,则说明没有两个StringBuffer对象是相等的。再比如Collections类,全部是静态方法,根本没必要创建对象,所以也就没有提供equals方法。
      我们程序中自定义的对象有时候需要比较它们是否相等,也需要重写equals方法。如果我们要将对象放到HashMap或者Hashtable这样的hash集合中的时候,就需要重写hashcode方法了。因为它们是根据hashcode来标识对象的。
      如果我们不重写hashcode方法,把他们作为key放入hashmap中是什么情况呢?看看下面代码:

Java代码 复制代码 收藏代码
  1. import java.util.HashMap;   
  2.   
  3. public class HashTest {   
  4.   
  5.     public static void main(String...args) {   
  6.         MyBean a = new MyBean();   
  7.         a.x = 1;   
  8.         a.s = "xyz";   
  9.         MyBean b = new MyBean();   
  10.         b.x = 1;   
  11.         b.s = "xyz";   
  12.         HashMap<MyBean, String> map = new HashMap<MyBean, String>();   
  13.         map.put(a, "a");   
  14.         map.put(b, "b");   
  15.         System.out.println("a equals b:"+a.equals(b));   
  16.         System.out.println("map size:"+map.size());   
  17.         System.out.println("a:"+map.get(a));   
  18.         System.out.println("b:"+map.get(b));   
  19.     }   
  20. }   
  21.   
  22. class MyBean {   
  23.     int x;   
  24.     String s;   
  25.     @Override  
  26.     public boolean equals(Object obj) {        
  27.         if(this == obj) return true;   
  28.         if(!(obj instanceof MyBean)) return false;   
  29.         if(((MyBean)obj).x == x) return true;   
  30.         return false;   
  31.     }   
  32. }  
import java.util.HashMap;

public class HashTest {

	public static void main(String...args) {
		MyBean a = new MyBean();
		a.x = 1;
		a.s = "xyz";
		MyBean b = new MyBean();
		b.x = 1;
		b.s = "xyz";
		HashMap<MyBean, String> map = new HashMap<MyBean, String>();
		map.put(a, "a");
		map.put(b, "b");
		System.out.println("a equals b:"+a.equals(b));
		System.out.println("map size:"+map.size());
		System.out.println("a:"+map.get(a));
		System.out.println("b:"+map.get(b));
	}
}

class MyBean {
	int x;
	String s;
	@Override
	public boolean equals(Object obj) {		
		if(this == obj) return true;
		if(!(obj instanceof MyBean)) return false;
		if(((MyBean)obj).x == x) return true;
		return false;
	}
}

      结果如下:

a equals b:true
map size:2
a:a
b:b  

      a和b明明是相等的,可是放进hashmap中之后,却被认为是两个对象,很诡异哦。
      下面加上hashcode,再看看什么结果:

Java代码 复制代码 收藏代码
  1. class MyBean {   
  2.     int x;   
  3.     String s;   
  4.     @Override  
  5.     public boolean equals(Object obj) {        
  6.         if(this == obj) return true;   
  7.         if(!(obj instanceof MyBean)) return false;   
  8.         if(((MyBean)obj).x == x) return true;   
  9.         return false;   
  10.     }   
  11.     @Override  
  12.     public int hashCode() {   
  13.         return (s!=null?s.hashCode():1)*31+x;   
  14.     }   
  15. }  
class MyBean {
	int x;
	String s;
	@Override
	public boolean equals(Object obj) {		
		if(this == obj) return true;
		if(!(obj instanceof MyBean)) return false;
		if(((MyBean)obj).x == x) return true;
		return false;
	}
	@Override
	public int hashCode() {
		return (s!=null?s.hashCode():1)*31+x;
	}
}

     结果如下:

a equals b:true
map size:1
a:b
b:b

 

      这样才保证了相等的对象在hash集合中也相等。计算hashcode的时候,一般使用关键的属性的hashcode值。计算hashcode的属性较多则计算复杂,降低了效率,若较少的属性计算,则重复的hashcode较多,同样降低性能,写一个好的hashcode方法,还比较难。
      所以,我们重写equals的时候,一定要重写hashcode方法。

分享到:
评论

相关推荐

    HashCode的用法详解

    如果我们不重写 hashCode(),那么对象的 hashCode 将会默认使用 Object 类中的 hashCode 方法,这样将会导致对象的存储位置不确定。 例如,如果我们有两个对象,它们的 hashCode 都是 1,那么它们将会被存放在同一...

    java中hashCode、equals的使用方法教程

    理解并正确地重写这两个方法对于优化程序性能和确保逻辑一致性具有重要意义。 1. **为什么使用`hashCode()`?** 在集合类如`HashSet`或`HashMap`中,`hashCode()`的主要作用是快速定位对象。当试图将一个对象添加...

    Java自动添加重写的toString方法详解

    然而,这样的输出对于调试和日志记录通常并不友好,所以我们常常需要重写`toString()`方法来提供更有意义的信息。 在Java中,`toString()`方法的重写通常是为了展示对象内部的状态,即它的成员变量的值。这样做可以...

    JAVA_bject类讲解

    通常,我们会重写这个方法来提供更有意义的字符串表示,比如类实例的状态信息。 5. **clone()方法**:`clone()`方法创建并返回当前对象的一个副本。这个方法涉及到浅拷贝和深拷贝的概念,需要注意的是,不是所有的...

    JavaSE基础入门视频教程33天之(15) part1

    为了调试或输出有意义的信息,常常需要重写此方法,返回一个描述对象状态的字符串。例如,你可以让一个用户类返回用户名和电子邮件的组合。 通过观看"day15_04(常用API)重写equals方法.avi","day15_03(常用API)...

    java-object类

    - **实现**:通常会在子类中重写该方法,以便返回更有意义的信息。 - **示例**: ```java public class Demo extends Object { private int id; private String name; // 构造函数 public Demo(int id, ...

    JavaSE之Object与Object类

    - 在实际应用中,我们通常会重写`toString()`方法,以便打印出对象的有意义的信息,如类的属性值。在示例中,`Person`类重写了`toString()`,输出了`Person{name='张三', age=18}`这样的格式。 2. **equals() 方法...

    Java软件开发实战 Java基础与案例开发详解 6-2 object类 共7页.pdf

    为了提供更有意义的信息,通常建议对自定义类重写`toString()`方法,以便返回一个更易于理解的字符串表示。 **示例代码**: ```java public class MyClass { private int myField; public MyClass(int myField) ...

    Android 面试-笔试题

    Java中 == 和 equals 和 hashCode 的区别 int、char、long 各占多少字节数 int 和 Integer 的区别 谈谈对Java多态的理解 String、StringBuffer、StringBuilder的区别 什么是内部类?内部类的作用 抽象类和接口的区别...

    注意对象的通用方法,类的设计陷阱.pdf

    - **重写equals和hashCode**:当自定义对象作为键存储在散列表中时,需要同时重写`equals()`和`hashCode()`方法,确保逻辑一致性。 - **toString()的重写**:提供更有意义的字符串表示,增强程序的可读性。 - **合理...

    Java学习笔记,面向对象深化

    因此,所有Java对象都有`Object`类提供的方法,如`toString()`、`equals()`和`hashCode()`。 5. **`toString()`方法**: - `Object`类的`toString()`方法返回类名加`@`加16进制的哈希码。在打印或连接对象时,默认...

    java简答题

    方法的重载是指多个方法具有相同的方法名,但具有不同的参数列表,方法的重写是指子类重写父类的方法。 本文总结了 Java 面试题中的知识点,涵盖了 Java 的基础知识、集合框架、数据库访问、多线程、面向对象编程等...

    Java Object类认识

    - 在重写`equals()`时,通常也需重写`hashCode()`,以保持两个方法的一致性,遵循equals和hashCode约定,确保当两个对象相等时,它们的哈希码也应该相等。 总结来说,理解`Object`类及其提供的方法是Java开发的基础...

    JAVA面试题-最全最新的八股文分类整理版

    如果只重写了equals而没有重写hashCode,则可能导致两个逻辑上相等的对象有不同的哈希值,从而导致集合中出现重复元素。 #### String、StringBuffer与StringBuilder的区别 - **String**:不可变字符串,每次修改...

    java课件 常用类与异常处理

    然而,对于具有实际业务意义的类,我们通常会重写`equals()`方法,以比较对象的属性或状态是否相等。例如,`String`类就重写了`equals()`,比较的是字符串的内容而不是引用。 `hashCode()`方法返回对象的散列码,...

    java个人总结.docx

    而`equals`方法默认也是比较对象的引用,但在很多类(如`String`)中被重写以比较对象的内容。对于基本数据类型的包装类,除了`Float`和`Double`,其他都实现了常量池,比如`Integer`在-128到127之间的值会复用对象...

    经典Java基础面试题集锦

    - **equals与hashCode的关系**:当重写`equals`方法时,通常还需要重写`hashCode`方法以确保一致性。这是因为在Java中,如果两个对象根据`equals`方法定义的规则相等,则它们的`hashCode`也应该相同。 4. **Java...

    day12_Object类、常用API.pdf

    toString()方法的源码中返回类的全限定名字和hashCode()方法返回的int值,可以暂时理解为对象的内存地址。Integer.toHexString()方法将int类型的值转成十六进制。因此调用对象的toString()方法将看到内存的地址值。 ...

    阿里面试官必问21个刁钻的HashMap面试题,这次让你彻底搞懂.docx

    4. **重写hashCode和equals方法的原因** 为了确保键的唯一性,需要重写这两个方法,使具有相同意义的对象能正确地映射到相同的哈希值,并且equals方法可以确认两个对象是否相等。 5. **hash函数的实现** JDK1.8中,...

Global site tag (gtag.js) - Google Analytics