List集合去除重复对象及equals()、hashCode()方法的作用
原文:https://blog.csdn.net/freelander_j/article/details/52211010
在java中,要将一个集合中重复的对象除去,如果这个集合中的数据类型是基本数据类型,可以直接将list集合转换成set,就会自动去除重复的元素,大家都知道set集合的特点就是没有重复的,这个就相对比较简单,这里不在详细说,我们下面说的list集合中的数据类型是一个对象类型的。
当list集合中存储的类型是对象类型的时候,我们就不能简单的只把list集合转换成set集合就行了,这时我们需要在对象的实体类中去重写equals()方法和hashCode()方法,我们以一个list集合为例,在该例中,我们将People实体类中姓名和电话号码作为判断该对象重复的标识,在People的实体类中我们重写这两个方法如下:
- public class People {
- private String name;
- private int id;
- private String phoneNumber;
- private int age;
- private String introduce;
- public People(String name, int id, String phoneNumber, int age,
- String introduce) {
- super();
- this.name = name;
- this.id = id;
- this.phoneNumber = phoneNumber;
- this.age = age;
- this.introduce = introduce;
- }
- // ....... 这里省略getter和setter方法
- @Override
- public boolean equals(Object arg0) {
- // TODO Auto-generated method stub
- People p = (People) arg0;
- return name.equals(p.name) && phoneNumber.equals(p.phoneNumber);
- }
- @Override
- public int hashCode() {
- // TODO Auto-generated method stub
- String str = name + phoneNumber;
- return str.hashCode();
- }
- }
以上实体类中,我们在equals()方法中取出该对象的name和phoneNumber这两个属性值去判断比较,然后在重写的hashCode()方法中返回这两个属性值得hashCode值。
- public class Test {
- public static void main(String[] args) {
- List<People> listPeople = new ArrayList<People>();
- listPeople.add(new People("张三", 1, "13355556666", 23, "新员工"));
- listPeople.add(new People("张三", 2, "15522223333", 23, "老员工"));
- listPeople.add(new People("李四", 3, "13355556666", 23, "实习生"));
- listPeople.add(new People("提莫", 4, "13311112222", 23, "经理"));
- listPeople.add(new People("张三", 5, "13355556666", 23, "会计"));
- listPeople.add(new People("德玛", 6, "3344", 23, "开发"));
- listPeople.add(new People("卡特", 7, "13355556666", 23, "测试"));
- listPeople.add(new People("提莫", 8, "13355556666", 23, "美工"));
- listPeople.add(new People("提莫", 9, "13311112222", 23, "实施"));
- listPeople.add(new People("卡兹克", 10, "13356786666", 23, "售前"));
- listPeople.add(new People("亚索", 11, "13355556666", 23, "销售"));
- Set<People> setData = new HashSet<People>();
- setData.addAll(listPeople);
- System.out.println("list- size----" + listPeople.size());
- System.out.println("list-----" + listPeople.toString());
- System.out.println("set- size----" + setData.size());
- System.out.println("set-----" + setData.toString());
- for(People pp : setData) {
- System.out.println("p--" + pp.toString());
- }
- }
- }
运行这段代码之后,我们就会发现,在原来的list集合中姓名和电话号码都相同的对象就被会认为是重复的元素而删除掉,很明显运行结果已经达到我们的目的。
这里需要说一下equals()方法和hashCode()方法,一般情况下我们重写equals()方法的时候都要去重写hashCode()方法,这是为什么呢?大家不妨可以这样去试一试上面那个例子,在实体类中将重写的hashCode()方法注释掉,再去运行该程序,这时就会发现运行结果并不是我们刚刚得到的结果,在set集合中,并没有将我们认为是重复的元素删除掉,下面我们通过这两个方法的源码去了解一下:
String类中的equals()方法的源码如下
- public boolean equals(Object anObject) {
- if (this == anObject) {
- return true;
- }
- if (anObject instanceof String) {
- String anotherString = (String)anObject;
- int n = count;
- if (n == anotherString.count) {
- char v1[] = value;
- char v2[] = anotherString.value;
- int i = offset;
- int j = anotherString.offset;
- while (n-- != 0) {
- if (v1[i++] != v2[j++])
- return false;
- }
- return true;
- }
- }
- return false;
- }
通过观察equals()方法的源码我们可以看出,该方法去比较两个对象时,首先先去判断两个对象是否具有相同的地址,如果是同一个对象的引用,则直接放回true;如果地址不一样,则证明不是引用同一个对象,接下来就是挨个去比较两个字符串对象的内容是否一致,完全相等返回true,否则false。
String类中hashCode()方法的源码如下
- public int hashCode() {
- int h = hash;
- if (h == 0 && count > 0) {
- int off = offset;
- char val[] = value;
- int len = count;
- for (int i = 0; i < len; i++) {
- h = 31*h + val[off++];
- }
- hash = h;
- }
- return h;
- }
以上是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()方法的作用的更多相关文章
- list集合去除重复对象的实现
下面小编就为大家带来一篇list集合去除重复对象的实现.小编觉得挺不错的,现在就分享给大家,也给大家做个参考.一起跟随小编过来看看吧 对象重复是指对象里面的变量的值都相等,并不定是地址.list集合存 ...
- 【java基础】java中Object对象中的Hashcode方法的作用
以下是关于HashCode的官方文档定义: hashcode方法返回该对象的哈希码值.支持该方法是为哈希表提供一些优点,例如,java.util.Hashtable 提供的哈希表. hashCode ...
- Java中List集合去除重复数据的四种方法
1. 循环list中的所有元素然后删除重复 public static List removeDuplicate(List list) { for ( int i = 0 ; i < lis ...
- C# List集合去除重复数据
实例如下: using System; using System.Collections.Generic; using System.Linq; using System.Windows.Forms; ...
- equals(),hashcode()方法详解
Java中的equals方法和hashCode方法是Object中的,所以每个对象都是有这两个方法的,有时候我们需要实现特定需求,可能要重写这两个方法,今天就来介绍一些这两个方法的作用. equals ...
- .hashCode方法的作用
对于包含容器类型的程序设计语言来说,基本上都会涉及到hashCode.在Java中也一样,hashCode方法的主要作用是为了配合基于散列的集合一起正常运行,这样的散列集合包括HashSet.Hash ...
- 类属性与对象实现,init方法的作用,绑定方法,绑定方法与普通函数的区别,继承,抽象与继承,派生与覆盖
今日内容: 1.类属性与对象属性 2.init方法的作用 3.绑定方法 4.绑定方法与普通函数的区别(非绑定方法) 5.继承 6.抽象与继承 7.派生与覆盖 1.类属性与对象属性 类中应该进存储所有对 ...
- 去除list集合中重复项的几种方法
因为用到list,要去除重复数据,尝试了几种方法.记录于此... 测试数据: List<string> li1 = new List<string> { "8&quo ...
- Android 去除list集合中重复项的几种方法
因为用到list,要去除重复数据,尝试了几种方法.记录于此... 测试数据: List<"}; List<string> li2 = new List<string& ...
随机推荐
- c# 行转列
将下面表(1)格式的数据转换为表(2)格式的数据.很明显,这是一个行转列的要求,本想在数据库中行转列,因为在数据库中行转列是比较简单的,方法可以参考本站SQLServer中(行列转换)行转列及列转行且 ...
- 【USACO 1.4】Combination Lock
/* TASK:combo LANG:C++ URL:http://train.usaco.org/usacoprob2?a=E6RZnAhV9zn&S=combo SOLVE:自己做,想的是 ...
- C/C++ Bug记录
链接错误解决方法 1. 检查库是否链接正确 2. 库的顺序是否合理(如果库之间有依赖关系的话) 3. 检查obj文件是否存在既有C编译的,也有C++编译的,如果存在,用extern "C&q ...
- 【题解】 bzoj1207: [HNOI2004]打鼹鼠 (动态规划)
bzoj1207,懒得复制,戳我戳我 Solution: 挺傻逼的一个\(dp\),直接推就好了 这题在bzoj上的数据有点问题,题目保证每个时间点不会出现在同一位置两个地鼠,然而他有= =(还浪费我 ...
- 学习Spring Boot:(十一) 自定义装配参数
前言 SpringMVC 中 Controller 中方法的参数非常灵活,得益于它的强大自动装配,这次将根据上次遗留下的问题,将研究下装配参数. 正文 SpringMVC中使用了两个接口来处理参数: ...
- 【arc074e】RGB Sequence(动态规划)
[arc074e]RGB Sequence(动态规划) 题面 atcoder 洛谷 翻译见洛谷 题解 直接考虑暴力\(dp\),设\(f[i][j][k][l]\)表示当前考虑到第\(i\)位,最后一 ...
- BZOJ 2561 最小生成树 | 网络流 最小割
链接 BZOJ 2561 题解 用Kruskal算法的思路来考虑,边(u, v, L)可能出现在最小生成树上,就是说对于所有边权小于L的边,u和v不能连通,即求最小割: 对于最大生成树的情况也一样.容 ...
- BZOJ3738 [Ontak2013]Kapitał 【扩展Lucas】
题目链接 BZOJ3738 题解 复习 同上 但是为了消去因子\(10\),处理\(2^k\)的时候,乘回\(2^{k_1}\)时,应同时计算\(5^{k_2}\) 如果\(k_1 \ge k_2\) ...
- 【codevs1245】最小的 N 个和
题目大意:给定两个有 N 个数字的序列,从这两个序列中任取一个数相加,共有 \(N^2\) 个和,求这些和中最小的 N 个. 题解:由于数据量是 10W,必须减少每次选取的决策集合中元素的个数.可以发 ...
- Java中如何遍历Map对象
方法一:使用map.entrySet()来遍历.这是最常见的并且在大多数情况下也是最可取的遍历方式.在键值都需要的时候使用. Map<String,String> map = new Ha ...