一,各个集合的特点:

  •   Collection(集合):容器,用于存放对象(引用类型。基本类型需要自动装箱)
  •   List(列表):元素有序,元素可以重复 (有索引)。 通过元素的equals()方法判断是否重复。
  •   Set(集):元素无序,不可重复 (没有索引)。 遍历只能用Iterator迭代器和增强for, 不能使用普通for遍历。
  •   ArrayList(数组列表): 查询快,增删慢。
  •   LinkedList(链表): 查询慢,增删快。
  •   HashSet(哈希表): 查询快,增删慢。 (底层其实就是Map) 。 存放的引用类型需重写hashCode()和equals()方法。
  •   LinkedHashSet(哈希链表): 查询慢,增删快。 有序的,存放顺序和取出顺序一致。

1.1,为什么要去重:

  •   在我们开发中,我们所读取的数据难免会有重复数据,我们需要的则是不重复数据的引用,所以需要对数据进行去重,
  •   而基本数据类型的去重比较好去重而引用数据类型呢,因为要判断hashCode运算是否相等,还有equals()是否相等,所以需要去重操作,
  •   我们以一个list集合为例,在该例中,我们将User实体类中姓名和电话号码作为判断该对象重复的标识,在User的实体类中我们重写
  •   这两个方法如下:
 package com.example.pojo;

 public class User {
private String name;
private String region;
private Integer performance;
public User(String name, String region, Integer performance) {
super();
this.name = name;
this.region = region;
this.performance = performance;
}
@Override
public String toString() {
return "User [name=" + name + ", region=" + region + ", performance=" + performance + "]";
}
@Override
public int hashCode() {
final int prime = ;
int result = ;
result = prime * result + ((name == null) ? : name.hashCode());
result = prime * result + ((performance == null) ? : performance.hashCode());
result = prime * result + ((region == null) ? : region.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
User other = (User) obj;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
if (performance == null) {
if (other.performance != null)
return false;
} else if (!performance.equals(other.performance))
return false;
if (region == null) {
if (other.region != null)
return false;
} else if (!region.equals(other.region))
return false;
return true;
}
}
  • 以上实体类中,我们在equals()方法中取出该对象的name与region和performance这三个属性值去判断比较,然后在重写的hashCode()
  • 方法中返回这三个属性值得equals对象地址值。

1.2,去重操作步骤:

 package com.example.arraylist;

 import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import com.example.pojo.User; /**
* @author Administrator
* 思路:
* 1.先对其文本文本进行添加,添加到List<User>中
* 2.把List<User>用迭代器进行迭代
* 3.创建一个新的集合,用来存储不重复的元素
* 4.用while(it.hasNext())有多少元素就循环多少次
* 4.判断新的集合是否有旧的元素如果没有则进行添加
*/
public class ListUserRepeat {
public static void main(String[] args) {
String string="张三,河北,90\n"+
"张三,河南,92\n"+
"李四,湖北,80\n"+
"王五,山西,88\n"+
"张三,河北,90\n"+
"李四,湖北,80\n"+
"马六,山东,77\n";
List<User> list = new ArrayList<>();
String[] split = string.split("\n");
for(String spl : split) {
String[] split2 = spl.split(",");
list.add(new User(split2[], split2[],Integer.parseInt(split2[])));
}
Iterator<User> it = list.iterator();
List<User> listOne = new ArrayList<>();
while(it.hasNext()) {
Object object = it.next();
if(!listOne.contains(object)) {
listOne.add((User) object);
}
}
for (User user : listOne) {
System.out.println(user);
}
}
}

运行这段代码之后,就会很明显的发现,list中重复的用户名,地区,都相同的对象就被会认为是重复的元素而删除掉,很明显运行结果已经达到我们的目的。

二,说一下为什么需要重写equals()方法和hashChode方法():

  • 一般情况下我们重写equals()方法的时候还要重写hashChode()方法,但是我们用的是list所以不用重写hashCode,大家不妨
  • 可以试试上面的例子,在实体类将重写的equals()方法注释掉,再运行程序,这时就会发现运行结果并不是我们刚刚得到的结果,(图中 我用的是list集合,
  • 不是set集合,list集合只需要重写equals()方法就行,而set集合则equals()和hashCode()方法都需要重写)

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

     public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = ;
while (n-- != ) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}

通过观察equals()方法的源码我们可以看出,该方法去比较两个对象时,首先先去判断两个对象是否具有相同的地址,如果是同一个对象的引用,则直接放回true;如果地址不一样,则证明不是引用同一个对象,接下来就是挨个去比较两个字符串对象的内容是否一致,完全相等返回true,否则false。

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

     public int hashCode() {
int h = hash;
if (h == && value.length > ) {
char val[] = value; for (int i = ; i < value.length; i++) {
h = * h + val[i];
}
hash = h;
}
return h;
}

以上是String类中重写的hashCode()方法,在Object类中的hashCode()方法是返回对象的32位JVM内存地址,也就是说如果我们不去重写该方法,将会返回该对象的32位JVM内存地址,以上我们测试的例子中,当注释掉重写的hashCode()方法时,这时默认返回对象的32JVM中的地址,两个不同的对象地址显然是不同的,我们在比较时,虽然通过重写的equals()方法比较出来name和phoneNumber值是相同的,但是默认的hashCode()方法返回的值他们并不是同一个对象,所以我们通常要将hashCode()方法与equals()方法一起重写,以维护hashCode方法的常规协定,该协定声明相等对象必须具有相等的哈希码。

总结:

  用白话说,通过hashCode判断对象是否放在同一个桶里,先确定他们在一个桶里面,然后再通过equals方法去判断这个桶里的对象是不是相同的。

List去重为什么要写equals(),hashCode()方法的更多相关文章

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

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

  2. Effective Java 第三版——11. 重写equals方法时同时也要重写hashcode方法

    Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...

  3. 如何编写出高质量的 equals 和 hashcode 方法?

    什么是 equals 和 hashcode 方法? 这要从 Object 类开始说起,我们知道 Object 类是 Java 的超类,每个类都直接或者间接的继承了 Object 类,在 Object ...

  4. Java基础知识点2:hashCode()方法

    hashCode()方法基本实现 hashCode方法是Java的Object类所定义的几个基本方法之一.我们可以深入到Object类的源码中去查看: public native int hashCo ...

  5. java中的 equals + hashCode

    [0]README 0.1)本文转自 core java volume 1, 旨在理清 equals + hashCode方法: [1]equals方法 1.1) Object中的 equals 方法 ...

  6. equals(),hashcode(),克隆学习心得

    equals(),hashcode(),克隆学习心得 其实在开发时候,很少去重写equals(),hashCode()方法,但是有些时候业务需要还是要重写. 注意: 重写equals()方法一定要重写 ...

  7. 千万不要误用 java 中的 HashCode 方法

    刚才debug追堆栈的时候发现一个很奇怪的问题 我用IE8和Google的浏览器访问同一个地址 Action的 scope="session" 也设置了 而且两个浏览器提交的参数m ...

  8. JavaSE的包装类,自动装箱和自动拆箱 ,字符窜转换,toString(),equals(), hashCode()的区别

    一.基本数据类型和包装类 包装类均位于Java.lang包,包装类和基本数据类型的对应关系如下表所示: Primitive-Type   Wrapper-Class        byte       ...

  9. [改善Java代码]覆写equals方法必须覆写hashCode方法

    覆写equals方法必须覆写hashCode方法,这条规则基本上每个Javaer都知道,这也是JDK API上反复说明的,不过为什么要这样做呢?这两个方法之间有什么关系呢?本建议就来解释该问题,我们先 ...

随机推荐

  1. Django_06_项目完成

    项目完成 基本知识点都学完了,接下来完成示例项目 现在还需要的代码包括三个方面,三个方面顺序不分先后 1.定义视图 2.定义URLconf 3.定义模板 定义视图 编写booktest/views.p ...

  2. storm入门基本知识

    引言 介绍storm之前,我先抛出这两个问题: 1.实时计算需要解决些什么问题? 2.storm作为实时计算到底有何优势? storm简介 官方介绍: Apache Storm is a free a ...

  3. OSI七层协议和TCP/IP四层协议

    1. OSI七层和TCP/IP四层的关系 1.1 OSI引入了服务.接口.协议.分层的概念,TCP/IP借鉴了OSI的这些概念建立TCP/IP模型. 1.2 OSI先有模型,后有协议,先有标准,后进行 ...

  4. 如何处理请求返回的二进制数据流转化成xlsx文件?

    /* fileName : 文件名 res:二进制流 */ function getOutExcel(fileName, res) { let blob = new Blob([res], { typ ...

  5. 统计连接到主机前十的ip地址和连接数

    常用脚本–tcp #!/bin/bash # #******************************************************************** #encodi ...

  6. Kubernetes1.16下部署Prometheus+node-exporter+Grafana+AlertManager 监控系统

    Prometheus 持久化安装 我们prometheus采用nfs挂载方式来存储数据,同时使用configMap管理配置文件.并且我们将所有的prometheus存储在kube-system #建议 ...

  7. UVALive 6859——凸包&&周长

    题目 链接 题意:在一个网格图上,给出$n$个点的坐标,用一个多边形包围这些点(不能接触,且多边形的边只能是对角线或直线),求多边形的最小周长. 分析 对于每个点,我们考虑与之相邻的4个点.一共由 $ ...

  8. [Spring Boot] Set Context path for application in application.properties

    If you were using Microservice with Spring Boot to build different REST API endpoints, context path ...

  9. 微信小程序填坑之旅(1)-app.js中用云开发获取openid,在其他页上用app.globaldata.openid获取为空

    参考:小程序如何在其他页面监听globalData中值的变化?https://www.jianshu.com/p/8d1c4626f9a3 原因就是:app.js没执行完时,其他页已经onload了, ...

  10. JVM(十一),垃圾回收之老年代垃圾收集器

    十一.垃圾回收之老年代垃圾收集器 1.Serial Old收集器(标记整理算法-单线程-Client模式下) 2.Paraller Old收集器(标记整理算法-多线程-) 3.CMS收集器(标记清除算 ...