Set\HashSet集合为什么能去重(转)

如果想查找一个集合中是否包含有某个对象,大概的程序代码怎样写呢?当发现某个元素与要查找的对对象进行equals方法比较的结果相等时,则停止继续查找并返回肯定的信息,否则返回否定的信息。如果是一个集合中有很多元素,譬如有一万个元素,并且没有包含要查找的对象时,则意味着你的程序需要从该集合中取出一万个元素进行啄一的比较才能得到结论,有人发明了一种hashCode算法,来提高查找的效率,这种方式将集合分成若干个存储区域,每个对象可以计算出一个哈希码,可以将哈希码分组,每组分别对应某个存储区域,根据一个对象的哈希码就可以确定该对象应该存储在哪个区域,

 

hashSet就是采用哈希算法存储对象的集合,它内部采用对某个数字n进行取余的方式对哈希码进行分组的划分对象的存储区域。Object中的hashCode用来返回对就java对象的哈希码,从而提高查找的效率。

为了保证一个类的实例对象能在HashSet正常存储,要求这个类的两个实例对象用equals()方法比较的结果相等时,它们的哈希码也必须相等,也就是说,如果obj1.equals(obj2)的结果为true,那么一下表达式的结果页要为true。

obj1.hashCode() == obj2.hashCode()

如果一个类的hashCode()方法没有遵循上述要求,那么,当这个的两个实例对象用equals()方法比较的结果相等时,它们本来应该无法同时存储进Set集合中,但是,如果将它们存储进HashSet集合中时,由于它们的hashCode()方法的返回值不同,第二个对象首先按哈希码计算可能会被放进与第一个对象不同的区域中,这样,它就不可能与第一个对象进行equals方法比较了,也就可能被存储进HashSet集合中了。Object类的hashCode()方法不能满足对象被存入到HashSet中的要求,因为它的返回值是通过对象的内存地址推算出来的,同一个对象在程序运行期间的任何时候返回的哈希值都是始终不变的,所以,只要是两个不同的实例对象,即使它们的equals方法比较结果相等,它们默认的hashCode方法的返回值是不同的。

提示:

(1)通常来说,一个类的两个实例对象用equals()方法比较的结果相等时,它们的哈希码也必须相等,但反之则不成立,即euqlas方法比较结果不相等的对象可以有相同的哈希码,或者说哈希码相同的两个对象的equals方法比较的结果可以不等,例如,字符串“BB”和"Aa"的euqals方法比较结果肯定不相等,但它们的hashCode方法返回值却相等。

(2)当一个对象被存储进HashSet集合中以后,就不能修改这个对象中的那些参与计算哈希值的字段了,否则,对象修改后的哈希值与最初存储进HashSet集合中时的哈希值就不同了,在这种情况下,即使在cantains方法使用该对象的当前引用作为的参数去HashSet集合中检索对象,也将返回找不到对象的结果。这也会导致从HashSet集合中单独删除当前对象,从而造成内存泄露。

时间: 2024-10-13 21:28:42

Set\HashSet集合为什么能去重(转)的相关文章

java 17 - 9 HashSet集合、TreeSet集合的练习

HashSet集合的练习 1 package zl_TreeSetTest; 2 /* 3 创建学生类 4 成员变量: 5 A:姓名 6 B:语文成绩 数学成绩 英语成绩 7 */ 8 public class Student { 9 private String name ; 10 private int chinese; 11 private int english; 12 private int math; 13 14 public Student() { 15 super(); 16 /

C# HashSet集合类型使用介绍

1.HashSet集合 使用HashSet可以提高集合的运算.使用HashSet集合不自带排序方法,如果需要排序的需求可以参考使用List<T>集合配合Sort方法. HashSet的优势在与运算快,作为一种存放在内存的数据,可以很快的进行设置和取值的操作.HashSet无法向里面添加重复的数据,避免添加HashSet<T>里面的数据重复.我们使用HashSet常常在集合相加集合相减这些集合与集合之间的操作之中. 使用HashSet作为内存存储的快速数据库,这个需要随时跟新Hash

JAVA学习第三十六课(常用对象API)- 集合框架(四)— Set集合:HashSet集合演示

随着Java学习的深入,感觉大一时搞了一年的ACM,简直是明智之举,Java里很多数据结构.算法类的东西,理解起来就轻松多了 Set集合下有两大子类开发常用 HashSet集合 .TreeSet集合 Set集合的元素是不重复且无序 一.HashSet集合 API文档解释:此类实现 Set 接口,由哈希表(实际上是一个 HashMap 实例)支持.它不保证 set 的迭代顺序:特别是它不保证该顺序恒久不变.此类允许使用null 元素. 此类为基本操作提供了稳定性能,注意,此实现不是同步的. 由上可

HashSet集合是如何保证元素的唯一性的?

HashSet集合的特点是元素无序和不重复 . 首先,HashSet的底层数据结构是哈希表.哈希表就是存储一系列哈希值的表,而哈希值是由对象的hashCode()方法生成的. 确保元素唯一性的两个方法,hashCode()和equals()方法. 当调用add()方法向集合中存入对象的时候,先比较此对象与原有对象的哈希值有没有一样的,如果都不一样就直接存入:如果有与之相同的哈希值,则要继续比较这两个对象是否为同一个对象,此时就要调用对象的equals()方法了. 总之,只有HashCode的至相

Java学习(set接口、HashSet集合)

一.set接口 概念:set接口继承自Collection接口,与List接口不同的是,set接口所储存的元素是不重复的. 二.HashSet集合 概念:是set接口的实现类,由哈希表支持(实际上是一个HashMap集合).HashSet集合元素的提取顺序与存储顺序不相同. 采用哈希表数据结构存储数据,保证元素唯一性的方式依赖于:hashCode()与equals()方法. 2.1哈希表 什么是哈希表? 链表与数组的组合. 哈希表底层使用的也是数组机制,数组中也存放对象,而这些对象往数组中存放时

HashSet集合的add()方法的源码

interface Collection { ... } interface Set extends Collection { ... } class HashSet implements Set { private static final Object PRESENT = new Object(); private transient HashMap<E,Object> map; public HashSet() { map = new HashMap<>(); } publi

如何在Mongodb集合中统计去重之后的数据

比方说我们有个Mongodb集合, 以这个简单的集合为例,我们需要集合中包含多少不同的手机号码,首先想到的应该就是使用distinct关键字, db.tokencaller.distinct('Caller').length 如果想查看具体的而不同的手机号码,那么可以省略后面的length属性,因为db.tokencaller.distinct('Caller')返回的是由所有去重手机号码组成的数组. 但是,这种方式对于所有情况都是满足的嘛?并不如此,如果要统计的集合记录数较大,如千万级别的,那

hashSet的实现原理去重

/* 集合 的体系: ------------| Collection 单例集合的根接口 ----------------| List 如果是实现了List接口的集合类,具备的特点: 有序,可重复. -------------------| ArrayList ArrayList 底层是维护了一个Object数组实现的. 特点: 查询速度快,增删慢. -------------------| LinkedList LinkedList 底层是使用了链表数据结构实现的, 特点: 查询速度慢,增删快

HashSet集合

1.HashSet Set集合,无索引,不可以重复,无序 在使用 list 集合时,add方法返回的永远时true,有序,有索引 在使用 Set 集合时,add方法再添加重复元素时,返回的false,无序,无索引 1 HashSet<String> hashSet = new HashSet<>(); 2 hashSet.add("t"); 3 hashSet.add("a"); 4 hashSet.add("b"); 5