HashSet存储过程中如何排除不同的自定义对象?
HashSet
HashSet存储过程中如何排除不同的自定义对象?
先看一个小demo
public class Demo1 {
public static void main(String[] args) {
//Person4类是一个失血模型,它有姓名和年龄两个属性
HashSet<Person4> set = new HashSet<>();
set.add(new Person4("张三", 23));
set.add(new Person4("张三", 23));
set.add(new Person4("李四", 24));
set.add(new Person4("李四", 24));
set.add(new Person4("李四", 24));
/*
* 直接打印,我们会发现,它把5个元素加入进去了,包括我们认为“重复”的元素
* 可是,HashSet不是号称不可重复吗?这是为什么?
*/
System.out.println(set);
}
}
HashSet在存储自定义的对象比如Person4(含name和age属性)时,如果存放name和age值相同的对象时,它都会存放进去。因为我们把它当作是相同的元素是根据它的属性值判断,而程序会为每个new出来的对象计算出不同的hashcode码,所以它认为是不同的对象,都会存放进去。
如何让它有效排除我们认为的“所有属性值相同的对象就是同一个对象”在这种定义下的同一种对象呢?
首先我们要去了解它的底层实现,即:
它判断是否相同的时候,肯定用了equals方法,他在计算hashcode的时候,应该用到了hashCode方法,那么它的执行流程和内部是怎么实现的呢?
我们追溯HashSet的源码,首先我们用到了add方法,它在add的时候肯定会进行是否存在相同对象的判断。我按住ctrl+鼠标左键点进去,一层一层追溯,结果懵逼了,发现里面涉及了很多以我目前实力看不懂的代码,怎么办?
先不管三七二十一,因为根据之前看源码的经验,我发现如果一个方法的底层如果用了equals方法,那么它调用的是obj的equals方法。什么意思呢?就是说它其实调用的是被操作对象的方法,我们每一个Person4对象的equals方法,这样实现的目的应该是为了我们使用者可以方便地重写equals方法底层实现从而实现我们自己的个性化使用。
我直接在person4里重写了equals方法如下:
@Override
public boolean equals(Object obj) {
//先把obj强制转换成person4对象
Person4 p = (Person4) obj;
//改成根据各属性的值判断是否同一个对象
return p.name.equals(this.name) && p.age == p.age;
}
再运行了下程序,发现并不起作用,重复元素还是存在。
我再一咬牙,再把hashCode方法一并改写了:
@Override
public int hashCode() {
return 10;
}
我让hashCode方法都返回10,发现重复元素都没了。
到了这里,不禁困惑,为什么这样就可以了呢?
后来,经过查阅资料,观看视频得知,hashSet底层的add方法大概流程是这样的:先比较hashcode码,不相同则插入成功,如果相同,则用equals比较。
再反观我们上面的程序,因为我让它hashcode都变成了10,所以他们最终都是通过equals比较的,equals被我重写,它就能够去掉重复的元素。
但是,实际开发中这样效率是不高的,我们应该让它尽可能少调用方法,达到效率的提升,特别是操作的元素数量特别多的时候。
所以,我们就应该让它在第一关:hashcode码判断的时候,就应该让不同的元素尽量返回不同的hashcode码,一次判断就结束。
如果你使用的是eclipse,那么可以利用它自带的便捷功能:自动重写equals和hashcode方法,并且实现了我们上面提的要求(它为我们考虑好了算法)。按住shift+alt+s,点击generate hashCode( ) and equals( ),他会自动重写我们的两个方法。你想学习它的算法怎么实现的,可以看它生成的代码。
HashSet存储过程中如何排除不同的自定义对象?的更多相关文章
- Web Service中的XFire 传输List 自定义对象.
我把这个创建的步骤和代码的贴出来,. 首先新建一个工程,取名就随便点啦..MyWebService,然后复制jar包到lib目录下, 创建包,建立接口..写一个javaBean的类, 以下是一个简单的 ...
- sqlserver 存储过程中使用临时表到底会不会导致重编译
曾经在网络上看到过一种说法,SqlServer的存储过程中使用临时表,会导致重编译,以至于执行计划无法重用, 运行时候会导致重编译的这么一个说法,自己私底下去做测试的时候,根据profile的跟踪结果 ...
- SQL Server存储过程中使用表值作为输入参数示例
这篇文章主要介绍了SQL Server存储过程中使用表值作为输入参数示例,使用表值参数,可以不必创建临时表或许多参数,即可向 Transact-SQL 语句或例程(如存储过程或函数)发送多行数据,这样 ...
- Java基础知识强化之集合框架笔记40:Set集合之HashSet存储自定义对象并遍历
1. HashSet存储自定义对象并遍历 2. 代码示例: (1)Student类,如下: package cn.itcast_02; /** * @author Administrator * */ ...
- Linq to Sql:N层应用中的查询(上) : 返回自定义实体
原文:Linq to Sql:N层应用中的查询(上) : 返回自定义实体 如果允许在UI层直接访问Linq to Sql的DataContext,可以省去很多问题,譬如在处理多表join的时候,我们使 ...
- 集合框架(HashSet存储自定义对象保证元素唯一性)
HashSet如何保证元素唯一性的原理 1.HashSet原理 a. 我们使用Set集合都是需要去掉重复元素的, 如果在存储的时候逐个equals()比较, 效率较低,哈希算法提高了去重复的效率, 降 ...
- 《java入门第一季》之HashSet存储自定义对象问题以及注意事项
上一篇http://blog.csdn.net/qq_32059827/article/details/51578158 写到存储字符串类型的时候出现了无序,而且这个无序不是随机那种无序,它是有一定存 ...
- JavaSE 集合类HashSet保证自定义对象唯一性
首先我们自定义Person类,只有姓名和年龄两个属性 class Person{ private String name ; private int age ; public Person(Strin ...
- 用HashSet存储自定义对象
案例 package cn.itcast_02; import java.util.HashSet; /* * 需求:存储自定义对象,并保证元素的唯一性 * 要求:如果两个对象的成员变量值都相同, ...
随机推荐
- C#中 Thread,Task,Async/Await,IAsyncResult 的那些事儿![转载]
说起异步,Thread,Task,async/await,IAsyncResult 这些东西肯定是绕不开的,今天就来依次聊聊他们 1.线程(Thread) 多线程的意义在于一个应用程序中,有多个执行部 ...
- NET Framework V4.0.30319
http://www.microsoft.com/zh-cn/download/details.aspx?id=17718
- MapServer:地图发布工具
MapServer简介:https://baike.baidu.com/item/MapServer
- OpenCV实现均值哈希
总共分三步:压缩,灰度化,均值化,求哈希值. 1.压缩 void secondMethod(char* filename, char* savename) { //const char* filena ...
- 编写高质量代码改善C#程序的157个建议——建议99:重写时不应使用子类参数
建议99:重写时不应使用子类参数 重写时,如果使用了子类参数,可能会偏离设计者的预期目标.比如,存在一个如下继承体系: class Employee { } class Manager : Emplo ...
- 洛谷P1501 [国家集训队]Tree II(打标记lct)
题目描述 一棵n个点的树,每个点的初始权值为1.对于这棵树有q个操作,每个操作为以下四种操作之一: + u v c:将u到v的路径上的点的权值都加上自然数c: - u1 v1 u2 v2:将树中原有的 ...
- RabbitMQ.Bus
一个.netcore下的,十分简单的rabbitmq封装,基于RabbitMQ.Client Nuget https://www.nuget.org/packages/RabbitMQ.Bus/ ht ...
- 使用Razor视图引擎来生成邮件内容
邮件的内容其实是就HTML,传统的做法都是通过在程序中拼接字符串来生成邮件的内容,生成困难,维护也困难.Razor是MVC里面使用的视图引擎,用来生成HTML非常方便,ZKEACMS中就是使用了Raz ...
- cesium编程入门(七)3D Tiles,模型旋转
cesium编程入门(七)3D Tiles,模型旋转 上一节介绍了3D Tiles模型的位置移动,和贴地的操作,这一节来聊一聊模型的旋转, 参考<WebGl编程指南>的第四章 假设在X轴和 ...
- Android 开发权限设置中英对照说明详解
android.permission.ACCESS_CHECKIN_PROPERTIES 允许读写访问 "properties"表在checkin数据库中,改值可以修改上传( Al ...