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. Spring.net 容器注入是替换(后处理器appConfigPropertyHolder)

    .定义节点 下面两个都定义为键值对 <section name="DaoConfiguration" type="System.Configuration.Name ...

  2. redis集群部署及常用的操作命令(上)

    简单说下自己测试搭建简单的redis集群的大体步骤: 1.首先你的有6个redis(官方说最少6个,3master,3slave),可以先在一台机器上搭建,搭建到多台上应该只需要改变启动命令即可(可能 ...

  3. Requests接口测试-对cookies的操作处理(二)

    我们继续来讨论一下cookie这方面的内容,我们都知道cookie是数据,一般的话在我接口测试中,数据都是要和代码进行分离的.本篇内容,我们队cookie内容进行处理,我们把登陆成功后的cookie写 ...

  4. 【转载】实战mysql分区(PARTITION)

    转载地址:http://lobert.iteye.com/blog/1955841 前些天拿到一个表,将近有4000w数据,没有任何索引,主键.(建这表的绝对是个人才) 这是一个日志表,记录了游戏中物 ...

  5. Android canvas bug

    安卓4.1.1-4.1.2的webkit在渲染canvas元素时有bug. 具体表现是出现重影,即canvas的clearRect()方法不能彻底清空画布,仍然保留之前某个状态当“背景”. 目前的修复 ...

  6. 重装ubuntu

    重装前 需要备份软件.配置文件等,重装系统时,最好不要重新给/home分区,也不要格式化,要不你需要备份很多东西,重装后也需要做很多设置.也就是说/home不格式化,整个重装系统都是很快的.最多花10 ...

  7. O_DIRECT方式读取文件示例

    #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <sys/stat.h& ...

  8. shell 编程 变量

    转自:http://blog.csdn.net/qq504196282/article/details/52994249 shell之变量和引用 分类:SHELL编程基础 (470)  (0)  举报 ...

  9. Linq转换操作之OfType,Cast,AsEnumerable,ToLookup源码分析

    Linq转换操作之OfType,Cast,AsEnumerable,ToLookup源码分析 一:Tolookup 1. 从方法的注解上可以看到,ToLookup也是一个k,v的形式,那么问题来了,它 ...

  10. CentOS 傻瓜式部署uWSGI + nginx + flask

    交代背景 这篇帖子是为了提供我自己的July Novel站点的小说数据支撑.解决分布式部署爬虫程序的繁琐过程,由于本人对shell编程并不熟悉,故而先逐步记录操作步骤,通过以下操作达到节省时间的方式. ...