原文: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. Hello 2018 A,B,C,D

    A. Modular Exponentiation time limit per test 1 second memory limit per test 256 megabytes input sta ...

  2. MT【166】青蛙跳

    (2015浙江重点中学协作体一模) 设ABCDEF为正六边形,一只青蛙开始在顶点A处,它每次可随意地跳到相邻两顶点之一.若在5次之内跳到D点,则停止跳动:若5次之内不能到达D点,则跳完5次也停止跳动. ...

  3. 【BZOJ4800】[Ceoi2015]Ice Hockey World Championship (meet in the middle)

    [BZOJ4800][Ceoi2015]Ice Hockey World Championship (meet in the middle) 题面 BZOJ 洛谷 题解 裸题吧,顺手写一下... #i ...

  4. 生成器 yield

    由于生成器的其中一种创建方式与列表推导式很相似,这里先说一下列表推导式. 列表推导式 列表推导式又叫列表生成式,官方叫做 list comprehension.顾名思义,这个是用来生成列表的. 用法: ...

  5. idea问题总结记录

    1.部署tomcat后,tomcat日志报错:java.lang.ClassNotFoundException 1.1 原因: tomcat虽然部署成功,但是并没有把本项目中访问服务器所需的类库加到W ...

  6. bzoj 3195 [Jxoi2012]奇怪的道路

    3195: [Jxoi2012]奇怪的道路 Description 小宇从历史书上了解到一个古老的文明.这个文明在各个方面高度发达,交通方面也不例外.考古学家已经知道,这个文明在全盛时期有n座城市,编 ...

  7. 用代码块在new对象时set属性

    看到这样一种用法,很方便 request.setRequestHead(new RequestHeadType() {{ setRequestor("Online"); setRe ...

  8. bzoj千题计划257:bzoj4199: [Noi2015]品酒大会

    http://www.lydsy.com/JudgeOnline/problem.php?id=4199 求出后缀数组的height 从大到小枚举,合并 维护组内 元素个数,最大.次大.最小.次小 # ...

  9. bzoj千题计划200:bzoj3106: [cqoi2013]棋盘游戏

    http://www.lydsy.com/JudgeOnline/problem.php?id=3106 白棋如果第一步不能赢,那么一定输 因为可以黑棋走的距离比白棋大,黑棋可以下一步吃掉白棋,也可以 ...

  10. HDU 3389 阶梯博弈变形

    n堆石子,每次选取两堆a!=b,(a+b)%2=1 && a!=b && 3|a+b,不能操作者输 选石子堆为奇数的等价于选取步数为奇数的,观察发现 1 3 4 是无法 ...