List集合去除重复对象及equals()、hashCode()方法的作用

来源:互联网 发布:php 判断大小 编辑:程序博客网 时间:2024/06/18 09:09

在java中,要将一个集合中重复的对象除去,如果这个集合中的数据类型是基本数据类型,可以直接将list集合转换成set,就会自动去除重复的元素,大家都知道set集合的特点就是没有重复的,这个就相对比较简单,这里不在详细说,我们下面说的list集合中的数据类型是一个对象类型的。

        当list集合中存储的类型是对象类型的时候,我们就不能简单的只把list集合转换成set集合就行了,这时我们需要在对象的实体类中去重写equals()方法和hashCode()方法,我们以一个list集合为例,在该例中,我们将People实体类中姓名和电话号码作为判断该对象重复的标识,在People的实体类中我们重写这两个方法如下:

[java] view plain copy
  1. public class People {  
  2.   
  3.     private String name;  
  4.     private int id;  
  5.     private String phoneNumber;  
  6.     private int age;  
  7.     private String introduce;  
  8.       
  9.     public People(String name, int id, String phoneNumber, int age,  
  10.             String introduce) {  
  11.         super();  
  12.         this.name = name;  
  13.         this.id = id;  
  14.         this.phoneNumber = phoneNumber;  
  15.         this.age = age;  
  16.         this.introduce = introduce;  
  17.     }  
  18.     // ....... 这里省略getter和setter方法  
  19.   
  20.     @Override  
  21.     public boolean equals(Object arg0) {  
  22.         // TODO Auto-generated method stub  
  23.         People p = (People) arg0;  
  24.         return name.equals(p.name) && phoneNumber.equals(p.phoneNumber);  
  25.     }  
  26.       
  27.     @Override  
  28.     public int hashCode() {  
  29.         // TODO Auto-generated method stub  
  30.         String str = name + phoneNumber;  
  31.         return str.hashCode();  
  32.     }  
  33.       
  34. }  
        以上实体类中,我们在equals()方法中取出该对象的name和phoneNumber这两个属性值去判断比较,然后在重写的hashCode()方法中返回这两个属性值得hashCode值。
[java] view plain copy
  1. public class Test {  
  2.       
  3.     public static void main(String[] args) {  
  4.               
  5.         List<People> listPeople = new ArrayList<People>();  
  6.         listPeople.add(new People("张三"1"13355556666"23"新员工"));  
  7.         listPeople.add(new People("张三"2"15522223333"23"老员工"));  
  8.         listPeople.add(new People("李四"3"13355556666"23"实习生"));  
  9.         listPeople.add(new People("提莫"4"13311112222"23"经理"));  
  10.         listPeople.add(new People("张三"5"13355556666"23"会计"));  
  11.         listPeople.add(new People("德玛"6"3344"23"开发"));  
  12.         listPeople.add(new People("卡特"7"13355556666"23"测试"));  
  13.         listPeople.add(new People("提莫"8"13355556666"23"美工"));  
  14.         listPeople.add(new People("提莫"9"13311112222"23"实施"));  
  15.         listPeople.add(new People("卡兹克"10"13356786666"23"售前"));  
  16.         listPeople.add(new People("亚索"11"13355556666"23"销售"));  
  17.           
  18.         Set<People> setData = new HashSet<People>();  
  19.         setData.addAll(listPeople);  
  20.           
  21.         System.out.println("list- size----" + listPeople.size());  
  22.         System.out.println("list-----" + listPeople.toString());  
  23.           
  24.         System.out.println("set- size----" + setData.size());  
  25.         System.out.println("set-----" + setData.toString());  
  26.           
  27.         for(People pp : setData) {  
  28.             System.out.println("p--" + pp.toString());  
  29.         }  
  30.           
  31.     }  
  32.       
  33.       
  34. }  
        运行这段代码之后,我们就会发现,在原来的list集合中姓名和电话号码都相同的对象就被会认为是重复的元素而删除掉,很明显运行结果已经达到我们的目的。

        这里需要说一下equals()方法和hashCode()方法,一般情况下我们重写equals()方法的时候都要去重写hashCode()方法,这是为什么呢?大家不妨可以这样去试一试上面那个例子,在实体类中将重写的hashCode()方法注释掉,再去运行该程序,这时就会发现运行结果并不是我们刚刚得到的结果,在set集合中,并没有将我们认为是重复的元素删除掉,下面我们通过这两个方法的源码去了解一下:

        String类中的equals()方法的源码如下

[java] view plain copy
  1. public boolean equals(Object anObject) {  
  2.     if (this == anObject) {  
  3.         return true;  
  4.     }  
  5.     if (anObject instanceof String) {  
  6.         String anotherString = (String)anObject;  
  7.         int n = count;  
  8.         if (n == anotherString.count) {  
  9.             char v1[] = value;  
  10.             char v2[] = anotherString.value;  
  11.             int i = offset;  
  12.             int j = anotherString.offset;  
  13.             while (n-- != 0) {  
  14.                 if (v1[i++] != v2[j++])  
  15.                     return false;  
  16.             }  
  17.             return true;  
  18.         }  
  19.     }  
  20.     return false;  
  21. }  
        通过观察equals()方法的源码我们可以看出,该方法去比较两个对象时,首先先去判断两个对象是否具有相同的地址,如果是同一个对象的引用,则直接放回true;如果地址不一样,则证明不是引用同一个对象,接下来就是挨个去比较两个字符串对象的内容是否一致,完全相等返回true,否则false。

        String类中hashCode()方法的源码如下

[java] view plain copy
  1. public int hashCode() {  
  2.     int h = hash;  
  3.     if (h == 0 && count > 0) {  
  4.         int off = offset;  
  5.         char val[] = value;  
  6.         int len = count;  
  7.   
  8.         for (int i = 0; i < len; i++) {  
  9.             h = 31*h + val[off++];  
  10.         }  
  11.         hash = h;  
  12.     }  
  13.     return h;  
  14. }  
        以上是String类中重写的hashCode()方法,在Object类中的hashCode()方法是返回对象的32位JVM内存地址,也就是说如果我们不去重写该方法,将会返回该对象的32位JVM内存地址,以上我们测试的例子中,当注释掉重写的hashCode()方法时,这时默认返回对象的32JVM中的地址,两个不同的对象地址显然是不同的,我们在比较时,虽然通过重写的equals()方法比较出来name和phoneNumber值是相同的,但是默认的hashCode()方法返回的值他们并不是同一个对象,所以我们通常要将hashCode()方法与equals()方法一起重写,以维护hashCode方法的常规协定,该协定声明相等对象必须具有相等的哈希码。

        曾在网上一篇博客中看到过这样的解释,用白话说,通过hashCode判断对象是否放在同一个桶里,然后再通过equals方法去判断这个桶里的对象是不是相同的,这个比喻也挺形象的。

阅读全文
0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 微信被太多人投诉被限制登录怎么办 微信账号被永久封号里面的钱怎么办 乱世王者领礼包时账号异常怎么办 qq填写资料见证号格式错误怎么办 如果把微信注销 王者的号怎么办 93元的吃鸡号忘了激活吗怎么办 王者荣耀实名注册不是自己的怎么办 苹果手机打开qq太慢了怎么办 剪辑视频打开了软件关闭不了怎么办 玩永恒纪元手游网络老掉线怎么办 绝地求生买的钥匙激活码忘了怎么办 魅族手机移动网络打不开网页怎么办 小米5s升级后下载不了软件怎么办 电脑可以登qq却开不了网页怎么办 手机微信图片没下载原图怎么办 qq号密码忘了密保忘了怎么办 扣扣更改密保手机失败怎么办 至尊宝安全模式密保手机更换怎么办 微信号手机号换了密码忘记了怎么办 被加盟网店托管骗了怎么办 善林金融倒闭投资者的钱怎么办? 微信支付密码忘了怎么办没绑卡 美团外卖没有骑手接单怎么办 发微信的"发送"没有了怎么办 华硕电脑下面的任务栏卡住了怎么办 微信登别人电脑上忘记退了怎么办 买手机买全新结果买到翻新机怎么办 苹果手机激活锁忘了id账号怎么办 淘宝很多产品都需要3c怎么办 小米mix装在兜里还能解锁怎么办 痰咳不出来憋的嘴唇紫了怎么办 京东闪电退款后不给退货怎么办 我的中国银行卡在异地被冻结怎么办 qq密保号码换了验证不了怎么办 qq登陆需要密保手机验证怎么办 微信漂流瓶被投诉收不到回复怎么办 电视的屏幕出现三条黑线怎么办 付了定金的房子不想要了怎么办 顾客刚买了东西就退怎么办 飞机票买了但是没有报团怎么办 日本寄东西回来深圳海关扣了怎么办