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存储过程中如何排除不同的自定义对象?的更多相关文章

  1. Web Service中的XFire 传输List 自定义对象.

    我把这个创建的步骤和代码的贴出来,. 首先新建一个工程,取名就随便点啦..MyWebService,然后复制jar包到lib目录下, 创建包,建立接口..写一个javaBean的类, 以下是一个简单的 ...

  2. sqlserver 存储过程中使用临时表到底会不会导致重编译

    曾经在网络上看到过一种说法,SqlServer的存储过程中使用临时表,会导致重编译,以至于执行计划无法重用, 运行时候会导致重编译的这么一个说法,自己私底下去做测试的时候,根据profile的跟踪结果 ...

  3. SQL Server存储过程中使用表值作为输入参数示例

    这篇文章主要介绍了SQL Server存储过程中使用表值作为输入参数示例,使用表值参数,可以不必创建临时表或许多参数,即可向 Transact-SQL 语句或例程(如存储过程或函数)发送多行数据,这样 ...

  4. Java基础知识强化之集合框架笔记40:Set集合之HashSet存储自定义对象并遍历

    1. HashSet存储自定义对象并遍历 2. 代码示例: (1)Student类,如下: package cn.itcast_02; /** * @author Administrator * */ ...

  5. Linq to Sql:N层应用中的查询(上) : 返回自定义实体

    原文:Linq to Sql:N层应用中的查询(上) : 返回自定义实体 如果允许在UI层直接访问Linq to Sql的DataContext,可以省去很多问题,譬如在处理多表join的时候,我们使 ...

  6. 集合框架(HashSet存储自定义对象保证元素唯一性)

    HashSet如何保证元素唯一性的原理 1.HashSet原理 a. 我们使用Set集合都是需要去掉重复元素的, 如果在存储的时候逐个equals()比较, 效率较低,哈希算法提高了去重复的效率, 降 ...

  7. 《java入门第一季》之HashSet存储自定义对象问题以及注意事项

    上一篇http://blog.csdn.net/qq_32059827/article/details/51578158 写到存储字符串类型的时候出现了无序,而且这个无序不是随机那种无序,它是有一定存 ...

  8. JavaSE 集合类HashSet保证自定义对象唯一性

    首先我们自定义Person类,只有姓名和年龄两个属性 class Person{ private String name ; private int age ; public Person(Strin ...

  9. 用HashSet存储自定义对象

      案例 package cn.itcast_02; import java.util.HashSet; /* * 需求:存储自定义对象,并保证元素的唯一性 * 要求:如果两个对象的成员变量值都相同, ...

随机推荐

  1. 【转】Comprehensive learning path – Data Science in Python

    Journey from a Python noob to a Kaggler on Python So, you want to become a data scientist or may be ...

  2. 浏览器透明设置例子,qt5.6才支持

    用simpleBrowser例子的基础上,在BrowserWindow构造函数修改如下 BrowserWindow::BrowserWindow(QWidget *parent, Qt::Window ...

  3. java Jvm工作原理学习笔记

    一.         JVM的生命周期 1.       JVM实例对应了一个独立运行的java程序它是进程级别 a)     启动.启动一个Java程序时,一个JVM实例就产生了,任何一个拥有pub ...

  4. 可排序的 COMB 类型 GUID

    最新代码在这儿:CombGuid.cs 首先这里不做GUID与整形作为主键的优劣之争,GUID自有它优势,但GUID本身是乱序的,会对索引的维护带来性能上的损耗,数据量越大越明显. COMB 类型 G ...

  5. C# 生成dll文件 并导入使用

    首先 在unity创建一个脚本 并编写内容,其中需要调用的方法.变量要公有化(也可以直接新建cs文件用编译器打开编译,但要先导入UnityEngine.dll). 然后,复制脚本关闭unity,在外界 ...

  6. C# 自带的.net类库 实现得到本机IP以及网关地址

    今天需要用到一个功能,获取主机名和本机的IP 准备用API实现的,然后稍微查了一下,发现.net类库已经有了 就在System.Net命名空间中的DNS类中 GetHostName 获取本地计算机的主 ...

  7. vs项目属性中的包含目录和库目录以及附加依赖项全都配置正确了,却还是提示:无法解析的外部符号

    这种情况下,很大可能是lib文件有问题 我是用vs编译下载的源代码文件得到的lib出现了如题的情况, 后来去网站上直接下载了lib文件,竟然解决了!-.-

  8. delphi edit边框成为下划线

    设置它的几个属性:BevelEdges    |_ beLeft = False;    |_ beTop   = False;    |_ beRight = False;    |_ beBott ...

  9. Fiddler2抓包

    https://www.cnblogs.com/conquerorren/p/8472054.html https://www.cnblogs.com/conquerorren/p/8472218.h ...

  10. Cntlm

    SourceForge页面 作用是转发请求到代理 可以同时加上域验证信息(为各种NTLM认证?) gradle.cmd.Terminal等工具或软件可能无法或者说没有使用系统/浏览器设置的代理,因为可 ...