论坛首页 入门技术论坛

Java中== equals hashcode浅析

浏览 17155 次
该帖已经被评为新手帖
作者 正文
   发表时间:2010-05-31   最后修改:2010-06-01
1. '=='是用来比较两个变量(基本类型和对象类型)的值是否相等的, 如果两个变量是基本类型的,那很容易,直接比较值就可以了。如果两个变量是对象类型的,那么它还是比较值,只是它比较的是这两个对象在栈中的引用(即地址)。
对象是放在堆中的,栈中存放的是对象的引用(地址)。由此可见'=='是对栈中的值进行比较的。如果要比较堆中对象的内容是否相同,那么就要重写equals方法了。
2. Object类中的equals方法就是用'=='来比较的,所以如果没有重写equals方法,equals和==是等价的。
通常我们会重写equals方法,让equals比较两个对象的内容,而不是比较对象的引用(地址)因为往往我们觉得比较对象的内容是否相同比比较对象的引用(地址)更有意义。
3. Object类中的hashCode是返回对象在内存中地址转换成的一个int值(可以就当做地址看)。所以如果没有重写hashCode方法,任何对象的hashCode都是不相等的。通常在集合类的时候需要重写hashCode方法和equals方法,因为如果需要给集合类(比如:HashSet)添加对象,那么在添加之前需要查看给集合里是否已经有了该对象,比较好的方式就是用hashCode。
4. 注意的是String、Integer、Boolean、Double等这些类都重写了equals和hashCode方法,这两个方法是根据对象的内容来比较和计算hashCode的。(详细可以查看jdk下的String.java源代码),所以只要对象的基本类型值相同,那么hashcode就一定相同。
5. equals()相等的两个对象,hashcode()一般是相等的,最好在重写equals()方法时,重写hashcode()方法; equals()不相等的两个对象,却并不能证明他们的hashcode()不相等。换句话说,equals()方法不相等的两个对象,hashcode()有可能相等。 反过来:hashcode()不等,一定能推出equals()也不等;hashcode()相等,equals()可能相等,也可能不等。在object类中,hashcode()方法是本地方法,返回的是对象的引用(地址值),而object类中的equals()方法比较的也是两个对象的引用(地址值),如果equals()相等,说明两个对象地址值也相等,当然hashcode()也就相等了。
以下是测试代码。
 public class Equals_HashCode {
    public static void main(String[] args) {        
         String a = new String("str");
         String b = new String("str");
         System.out.println(a==b);
         System.out.println(a.equals(b));
         System.out.println(a.hashCode());
         System.out.println(b.hashCode());
         // 输出 false true 114225 114225
         class A{
             String str;
             int i;
             public A(String str, int i) {
                 super();
                 this.str = str;
                 this.i = i;
             }
         }
         A aA = new A("str",1);
         A bA = new A("str",1);
         System.out.println(aA==bA);
         System.out.println(aA.equals(bA));
         System.out.println(aA.hashCode());
         System.out.println(bA.hashCode());
         // 输出 false false 6413875 21174459
         class B{
             String str;
             public B(String str){
                 this.str = str;
             }
         }
         B aB = new B("str");
         B bB = new B("str");
         System.out.println(aB==bB);
         System.out.println(aB.equals(bB));
         System.out.println(aB.hashCode());
         System.out.println(bB.hashCode());
         // 输出 false false 827574 17510567
         class C{
             int i;
             public C(int i){
                 this.i = i;
             }
         }
         C aC = new C(1);
         C bC = new C(1);
         System.out.println(aC==bC);
         System.out.println(aC.equals(bC));
         System.out.println(aC.hashCode());
         System.out.println(bC.hashCode());
         //输出 false false 27744459  28737396
    }
 
}
 
   发表时间:2010-06-01  
引用

equals()相等的两个对象,hashcode()一定相等; equals()不相等的两个对象,却并不能证明他们的hashcode()不相等。

是这样吗?我做了个测试
class Product {
	private int id;
	private String name;
	
	public Product(int id, String name) {
		this.id = id;
		this.name = name;
	}
	
	@Override 
	public boolean equals(Object obj) {
		if (obj == null) {
			return false;
		}
		if (!(obj instanceof Product)) {
			return false;
		}
		Product other = (Product)obj;
		if (other.id != this.id) {
			return false;
		}
		return true;
	}
}


public class EqualsTest {
	public static void main(String[] args) {
		Product a = new Product(1, "zcl");
		Product b = new Product(1, "chunlei");

		System.out.println("equals: " + a.equals(b)); 
		System.out.println("a.hashCode:" + a.hashCode()); 
		System.out.println("b.hashCode:" + b.hashCode());
	}
}
/** (output)

D:\My Documents\javacode>javac EqualsTest.java

D:\My Documents\javacode>java EqualsTest
equals: true
a.hashCode:12677476
b.hashCode:33263331

*/

是我理解错了还是楼主讲得有问题?
0 请登录后投票
   发表时间:2010-06-01  
五月天 写道
引用

equals()相等的两个对象,hashcode()一定相等; equals()不相等的两个对象,却并不能证明他们的hashcode()不相等。

是这样吗?我做了个测试
class Product {
	private int id;
	private String name;
	
	public Product(int id, String name) {
		this.id = id;
		this.name = name;
	}
	
	@Override 
	public boolean equals(Object obj) {
		if (obj == null) {
			return false;
		}
		if (!(obj instanceof Product)) {
			return false;
		}
		Product other = (Product)obj;
		if (other.id != this.id) {
			return false;
		}
		return true;
	}
}


public class EqualsTest {
	public static void main(String[] args) {
		Product a = new Product(1, "zcl");
		Product b = new Product(1, "chunlei");

		System.out.println("equals: " + a.equals(b)); 
		System.out.println("a.hashCode:" + a.hashCode()); 
		System.out.println("b.hashCode:" + b.hashCode());
	}
}
/** (output)

D:\My Documents\javacode>javac EqualsTest.java

D:\My Documents\javacode>java EqualsTest
equals: true
a.hashCode:12677476
b.hashCode:33263331

*/

是我理解错了还是楼主讲得有问题?

重写equal方法 一定要重写hashcode方法
1 请登录后投票
   发表时间:2010-06-01  
引用

重写equal方法 一定要重写hashcode方法

也不一定吧?我觉得也只是在处理如HashMap,HashSet等通过哈希储存结构中会使用到hashCode。
当然,在重写equals方法时同时重写hashCode是个好的规范!
我刚才那代码只是想证明:equals方法判断对象相等时,hashCode不一定相等。
0 请登录后投票
   发表时间:2010-06-01   最后修改:2010-06-01
五月天 写道
引用

重写equal方法 一定要重写hashcode方法

也不一定吧?我觉得也只是在处理如HashMap,HashSet等通过哈希储存结构中会使用到hashCode。
当然,在重写equals方法时同时重写hashCode是个好的规范!
我刚才那代码只是想证明:equals方法判断对象相等时,hashCode不一定相等。

之前没考虑好这个问题,在此表示歉意。《Effective Java》中也提到重写equal方法,规范性地也需要重写hashCode()。
真是知识到用时方狠少呀。
0 请登录后投票
   发表时间:2010-06-01  
tottichen 写道
五月天 写道
引用

重写equal方法 一定要重写hashcode方法

也不一定吧?我觉得也只是在处理如HashMap,HashSet等通过哈希储存结构中会使用到hashCode。
当然,在重写equals方法时同时重写hashCode是个好的规范!
我刚才那代码只是想证明:equals方法判断对象相等时,hashCode不一定相等。

之前没考虑好这个问题,在此表示歉意。《Effective Java》中也提到重写equal方法,规范性地也需要重写hashCode()。
真是知识到用时方狠少呀。


1. 你是不是需要两个object判断相等? 如果如楼上希望的product a product b那样就表示相等的话,在重写一下hashcode就可以了

2. 如果equals认为相等的两个对象,那hashcode一定相等;两个equals认为不相等的对象,hashcode不必需要不等

3. 为什么equals复写的时候必须复写hashcode
你在使用一些collection framework比如,hashtable的时候,当让希望不equals的对象有不同的hash值。
0 请登录后投票
   发表时间:2010-06-02  
这种浅析很没依据,测试代码也不足以说明观点。

文章苍白无力。
0 请登录后投票
   发表时间:2010-06-02  
2. 如果equals认为相等的两个对象,那hashcode一定相等;两个equals认为不相等的对象,hashcode不必需要不等。

hashCode方法到底返回了什么?如果是对象的引用(地址),那么两个equals不相等时,对象不会有相同的引用吧,引用不同,hashCode必然不等啊?!
0 请登录后投票
   发表时间:2010-06-02  
五月天 写道
引用

重写equal方法 一定要重写hashcode方法

也不一定吧?我觉得也只是在处理如HashMap,HashSet等通过哈希储存结构中会使用到hashCode。
当然,在重写equals方法时同时重写hashCode是个好的规范!
我刚才那代码只是想证明:equals方法判断对象相等时,hashCode不一定相等。

对,只是一个规范而已,主要作用是提高对象存在HashMap,HashSet中的查找效率。其它地方用不到
0 请登录后投票
   发表时间:2010-06-02  
banfry 写道
五月天 写道
引用

重写equal方法 一定要重写hashcode方法

也不一定吧?我觉得也只是在处理如HashMap,HashSet等通过哈希储存结构中会使用到hashCode。
当然,在重写equals方法时同时重写hashCode是个好的规范!
我刚才那代码只是想证明:equals方法判断对象相等时,hashCode不一定相等。

对,只是一个规范而已,主要作用是提高对象存在HashMap,HashSet中的查找效率。其它地方用不到


不是查找效率的问题,是如果你equals相等而hashcode不相等时,你在hashMap里会找不到。不是效率问题,是对错问题。

先找hashcode,hashcode不等的,直接认为不等。相等的,再看equals,两者都等,才算等。
1 请登录后投票
论坛首页 入门技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics