原文: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. 用宏实现C/C++从非零整数开始的数组

    相信大家在刚学习C/C++时,都会对数组下标从0开始编号有疑惑.尽管我是喜欢从0开始编号的“0党”,但是也有很多的人是喜欢从1开始编号. 意识到C/C++数组与指针具有一定的相似性后,我开始构思如何仿 ...

  2. 数位DP复习小结

    转载请注明原文地址http://www.cnblogs.com/LadyLex/p/8490222.html 之前学数位dp的时候底子没打扎实 虚的要死 这次正好有时间……刷了刷之前没做的题目 感觉自 ...

  3. BZOJ 百题纪念!

    一百题辣! 现在NOI知识点中最基础的那部分已经学完了--这几天发现自己会写SA啊树剖啊可持久化Trie啊之类模板题--还挺开心的-- 逛了两天学长博客之后--BZOJ100题辣--也挺开心的-- 现 ...

  4. 小记之while循环条件的操作位置

    # 判断条件时自减操作 (循环体判断 len == 0) > 执行顺序为,while(len) → len-- → 循环体 while(len--) { == len) { *buf = i2c ...

  5. 生成器python

    一.列表生成式 需求:看列表[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],我要求你把列表里的每个值加1,你怎么实现?你可能会想到2种方式 >>> a [0, 1, 2 ...

  6. angularJs实现级联操作

    angular实现级联非常的方便比起传统的jq和js来说,一般我们肯定是从后台获取一个list,然后生成一个下拉框,然后选中一个下拉框,得到id,再得到下一个list. 这些angular都给我做好了 ...

  7. 读asyncio模块源码时的知识补漏

    硬着头皮看了一周的asyncio模块代码,了解了大概的执行流程,引用太多,成尤其是对象间函数的引用. 光是这么一段简单的代码: # coding: utf8 import asyncio import ...

  8. 10个造型奇特的css3进度条(有的html被编辑器转义了,上面的代码还是OK的)。。。转载

    <div id="caseVerte"> <div id="case1"></div> <div id="c ...

  9. 菜鸟学习Spring Web MVC之一

    ---恢复内容开始--- 当当当!!沉寂两日,学习Spring Web MVC去了.吐槽:近日跟同行探讨了下,前端攻城师,左肩担着设计师绘图,右肩担着JAVA代码?!我虽设计过UI,但这只算是PS技巧 ...

  10. AngularJS入门基础——表达式

    表达式在AngularJS应用中广泛的使用,因此深入理解AngularJS如何使用并运算表达式是非常重要的.   表达式和eval非常相似,但是由于表达式由AngularJS来处理,它们有已下显著不同 ...