`

重写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方法。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics