原文:https://blog.csdn.net/freelander_j/article/details/52211010

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

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

  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值。

  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()方法的源码如下

  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()方法的源码如下

  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方法去判断这个桶里的对象是不是相同的,这个比喻也挺形象的。

关于hashCode方法的作用大家可以看看这篇博客,讲的很清楚:http://blog.csdn.net/fenglibing/article/details/8905007

List集合去除重复对象及equals()、hashCode()方法的作用的更多相关文章

  1. list集合去除重复对象的实现

    下面小编就为大家带来一篇list集合去除重复对象的实现.小编觉得挺不错的,现在就分享给大家,也给大家做个参考.一起跟随小编过来看看吧 对象重复是指对象里面的变量的值都相等,并不定是地址.list集合存 ...

  2. 【java基础】java中Object对象中的Hashcode方法的作用

    以下是关于HashCode的官方文档定义: hashcode方法返回该对象的哈希码值.支持该方法是为哈希表提供一些优点,例如,java.util.Hashtable 提供的哈希表. hashCode  ...

  3. Java中List集合去除重复数据的四种方法

    1. 循环list中的所有元素然后删除重复   public static List removeDuplicate(List list) { for ( int i = 0 ; i < lis ...

  4. C# List集合去除重复数据

    实例如下: using System; using System.Collections.Generic; using System.Linq; using System.Windows.Forms; ...

  5. equals(),hashcode()方法详解

    Java中的equals方法和hashCode方法是Object中的,所以每个对象都是有这两个方法的,有时候我们需要实现特定需求,可能要重写这两个方法,今天就来介绍一些这两个方法的作用. equals ...

  6. .hashCode方法的作用

    对于包含容器类型的程序设计语言来说,基本上都会涉及到hashCode.在Java中也一样,hashCode方法的主要作用是为了配合基于散列的集合一起正常运行,这样的散列集合包括HashSet.Hash ...

  7. 类属性与对象实现,init方法的作用,绑定方法,绑定方法与普通函数的区别,继承,抽象与继承,派生与覆盖

    今日内容: 1.类属性与对象属性 2.init方法的作用 3.绑定方法 4.绑定方法与普通函数的区别(非绑定方法) 5.继承 6.抽象与继承 7.派生与覆盖 1.类属性与对象属性 类中应该进存储所有对 ...

  8. 去除list集合中重复项的几种方法

    因为用到list,要去除重复数据,尝试了几种方法.记录于此... 测试数据: List<string> li1 = new List<string> { "8&quo ...

  9. Android 去除list集合中重复项的几种方法

    因为用到list,要去除重复数据,尝试了几种方法.记录于此... 测试数据: List<"}; List<string> li2 = new List<string& ...

随机推荐

  1. Gym 100463A Crossings (树状数组 逆序对)

    Crossings Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/100463 Description ...

  2. 转头条:阿里p7架构师:三年经验应该具备什么样的技能?

    问:工作中,有时候实现一个功能,会去看有没有现成的轮子可用.对于重复造轮子与改造轮子有什么看法? 答:一定会的,其实这也是一个提高技术能力的方法,比如今天想做个日期转换的功能,JDK8有日期的新特性就 ...

  3. bzoj千题计划273:bzoj4710: [Jsoi2011]分特产

    http://www.lydsy.com/JudgeOnline/problem.php?id=4710 答案=总方案数-不合法方案数 f[i][j] 前i种特产分给j个人(可能有人没有分到特产)的总 ...

  4. ngx_lua_API 指令详解(六)ngx.thread.spawn、ngx.thread.wait、ngx.thread.kill介绍

    摘要:通过lua-nginx-module中的ngx.thread同时执行多个任务. ngx_lua中访问多个第三方服务 ngx_lua中提供了ngx.socket API,可以方便的访问第三方网络服 ...

  5. spark DataFrame 常见操作

    spark dataframe派生于RDD类,但是提供了非常强大的数据操作功能.当然主要对类SQL的支持. 在实际工作中会遇到这样的情况,主要是会进行两个数据集的筛选.合并,重新入库. 首先加载数据集 ...

  6. 新.Net架构必备工具列表

    N多年前微软官网曾发了.Net下必备的十种工具,N多年过去了,世异时移,很多东西都已经变化了,那个列表也似乎陈旧了.而且,该文也只是对十种工具独立的介绍,显得有些罗列的感觉,是不是每个工具都是同等重要 ...

  7. 20155203 2016-2017-2 《Java程序设计》第7周学习总结

    20155203 2016-2017-2 <Java程序设计>第6周学习总结 教材学习内容总结 1.Lambda表达式.(使用interface函数接口) 2.Lambda的方法参考Met ...

  8. HDU 2056 龟兔赛跑 (DP)

    题意:见题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2059 解题报告:以前一直没看出来这题是个DP题,知道是DP题就简单了 .首先要把起点和终点看成 ...

  9. supperset (python 2.7.12 + mysql)记录

    网上看到superset,比较感兴趣,虚机上搭一下,记录操作过程. 版本信息:CentOS 6.6 + python 2.7.12 + mysql 5.1.73 + setuptools 36.5.0 ...

  10. jquery的clone方法bug的修复select,textarea的值丢失

    项目中多次使用了iframe,但是操作起来是比较麻烦,项目中的现实情况是最外面是一个form,里面嵌套一个iframe,下面是一个其他的数据,在form提交的时候将iframe的数据和其他的数据一块提 ...