加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

hashSet中的equals方法和hashCode方法

(2013-11-25 14:40:13)
分类: TW

转自:http://blog.csdn.net/benjaminzhang666/article/details/9468487

 

没有重写equals

示例代码

 

  1. //2. 验证唯一性,存入自定义元素  
  2. class Person{  
  3.     private String name;  
  4.     private int age;  
  5.      
  6.     public static void sop(Object o){  
  7.         System.out.println(o);  
  8.      
  9.    
  10.     public Person(String name, int age){  
  11.         this.name =name;  
  12.         this.age =age;  
  13.      
  14.    
  15.     public void setName(String name){  
  16.         this.name =name;  
  17.      
  18.      
  19.     public String getName(){  
  20.         return this.name;  
  21.      
  22.    
  23.     public void setAge(int age){  
  24.         this.age =age;  
  25.      
  26.    
  27.     public int getAge(){  
  28.         return this.age;  
  29.      
  30.    
  31.     public String toString(){  
  32.         return this.name+"::"+this.age;  
  33.      
  34.  

测试代码:

  1. class HashSetDemoIII  
  2.  
  3.     public static void sop(Object o){  
  4.         System.out.println(o);  
  5.      
  6.    
  7.     public static void main(String[] args){  
  8.         HashSeths =new HashSet();  
  9.         hs.add(new Person("a1"11));  
  10.         hs.add(new Person("a2"12));  
  11.         hs.add(new Person("a3"13));  
  12.         hs.add(new Person("a2"12));  
  13.    
  14.         Iteratorit =hs.iterator();  
  15.         while(it.hasNext()){  
  16.             sop(it.next());  
  17.          
  18.      

 

 

 

测试结果:

测试结果:

http://img.blog.csdn.net/20130725142618125?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMTQwNjEyNA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast

 

【结论】循环迭代结果:a2::12打印了两次,说明重复的元素new Person("a2", 12)被添加到集合中去。没有保证HashSet的唯一性。

{3}. 为Person类重写equals()方法判定两个对象的内容是否一致

 

  1. public boolean equals(Object obj){  
  2. if(!(obj instanceof Person)){  
  3.         return false 
  4.      
  5.      
  6.     Personp =(Person)obj;  
  7.    
  8.     //用来查看equals方法是否被调用  
  9.     sop(this.name +".......equals......."p.name);  
  10.     //认为名字相同并且年龄一样大的两个对象是一个  
  11. return this.name.equals(p.name) && this.age == p.age;  
  12.  


 

 

测试结果:

http://img.blog.csdn.net/20130725142618125?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMTQwNjEyNA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast

 

【结论】循环迭代结果:a2::12打印了两次,说明重复的元素new Person("a2", 12)被添加到集合中去。没有保证HashSet的唯一性。

同时equals没有被调用,说明仅仅重写equals方法没起到作用

 

【分析】HashSet在存储元素的时候,是先查看两个对象的哈希值是否一样的。

{3}1.

如果哈希值一样再调用元素对象的equals方法,查看两个对象的内容是否一样。

{1}. 如果equlas比较的值一样,说明两个对象相同能添加到HashSet对应的集合中。

{2}. 如果equlas比较的值一样,说明两个对象可以添加到HashSet对应的集合中

 

{3}2.

       如果哈希值不一样,直接认为两个对象不一样,equals方法不起作用

【本例分析】这个例子中,由于四个Person类的对象都是new出来的,所以没有重写的hashCode是调用本地方法产生的值,所以一定是四个不相同的hashCode值。hashCode值都不一样,equals方法不起作用。

(3). 重写HashCode方法

为避免内容重复的数据添加到HashSet集合中,就必须重写hashCode()方法。

[1]. hashCode的返回值设置为统一的数值:

示例代码:

 

  1. public int hashCode(){  
  2.     System.out.println(this.name +"...hashCode");  
  3.     return 60 
  4.  


 

 

打印结果:

http://img.blog.csdn.net/20130725142818718?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMTQwNjEyNA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast


重复的元素没有被添加进来。

【建议】不要将hashCode的返回值都设置成一样的。因为hashCode的值和内存地址有关,这样设置不科学

[2]. 根据比较的条件重写HashCode方法

 

  1. public int hashCode(){  
  2.     sop(this.name +"......hashCode");  
  3.     return this.name.hashCode() 29*age;  
  4.  


 

 

这种做法,同样可以避免HashSet集合中不会存入相同元素。

【两种方式的具体区别和详细过程见个人总结。】

(4). 重写hashCode和equals的时候,常犯的错误

[1]. 子类重写hashCode的时候,将方法名写错,写成hasCode

[2]. 子类重写equals的时候,将参数传错,本来应该是public boolean equals(Object obj){}却写成了public boolean equals(自定义类型自定义类型引用)。这样集合框架的底层不会调用这个重载的方法。

2.    HashSet总结

1). HashCode如何保证元素唯一性?

(1). 需要重写的方法

通过重写自定义类hashCode()equals( )两个方法来达到元素的唯一性保证。

(2). 方法重写之后,执行的顺序

[1]. 如果元素hashCode相同,才会使用equals()方法进行判断。

[2]. 如果元素hashCode不同不会调用equals()方法

2). 开发中的建议

(1). 自定义对象,一定要重写hashCode和equals两个方法

       如果不重写,则默认的本地方法hashCode【OS来产生】会产生值都不一样的hashCode,即使内容重复的元素会被添加到HashSet中,无法保证元素的唯一性

【注意】开发中重写这两个方法,方便集合框架的底层调用这些方法。

(2). 建立高效的hashCode会使得hashSet添加元素的过程更为高效。

       hashCode的值不同,则调用equals()方法比较的环节便可以省去。

3). HashSet判断和删除元素的依据

示例代码:

 

  1.  public class HashSetDemoIV  
  2.     public static void main(String[] args)  
  3.         HashSeths =new HashSet();  
  4.         hs.add(new Person("a1"11));  
  5.         hs.add(new Person("a2"12));  
  6.         hs.add(new Person("a3"13));  
  7.         System.out.println("hashSet中的元素:"hs);  
  8.          
  9.         System.out.println("************************");  
  10.         System.out.println("HashSet的 contains依据:"hs.contains(new Person("a1"11)));  
  11.          
  12.         System.out.println("************************");  
  13.         System.out.println("HashSet的 remove依据:"hs.remove(new Person("a3"13)));  
  14.         System.out.println("************************");  
  15.         System.out.println("hashSet中的元素:"hs);  
  16.      
  17.  


 

 

打印结果:

http://img.blog.csdn.net/20130725142939718?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMTQwNjEyNA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast

可以看出,hashSet在删除和判断元素的时候,依据的仍然是hashCode和equals这两个方法。

结论:

[1]. HashSet判断删除添加元素等操作依据的是被操作元素所在的类的hashCode()equals( )这两个方法。

[2]. ArrayList做同等的操作,依据的仅仅是equals( )方法

 

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有