Java的HashSet类
如果要查找一个集合中是否包含了某个对象,那么就需要把这个对象和这个集合中的每个对象依次进行比较和判断,直到找到这个对象为止,或者把所有对象都比较一次为止(如果最后一个对象才是要查找的对象,或者集合中没有包含要查找的对象)。当集合中的对象数量较多时,效率就很低。为了提高效率,提出了Hash算法。Hash算法对每一个对象都计算出一个Hash码,根据Hash码把对象分配到某个存储区域中,比如一个集合包含了很多人,根据国籍,中国人是一个存储区域,美国人是一个存储区域,英国人是一个存储区域,......。这样如果要查找该集合是否包含了某个中国人,就到中国人的存储区域去比较就行了,这样大大提高了效率。
Java中实现了Hash的集合是HashSet。HashSet查找某个对象时,首先用hashCode()方法计算出这个对象的Hash码,然后再根据Hash码到相应的存储区域用equals()方法查找,从而提高了效率。由于是集合,所以同一个对象只能有一个。
hashSet的例子如下所示:
package my; import java.util.HashSet;
import java.util.Set; class Person{ // 性别
String sex;
// 姓名
String name;
// 身高
Double hei;
// 体重
Double wei; public Person(String n, String s, Double h, Double w){
this.name=n;
this.sex=s;
this.hei=h;
this.wei=w;
} public String toString(){
return "\n姓名:"+this.name+" 性别:"+this.sex+" 身高:"+this.hei+" 体重:"+this.wei;
} } public class myHS { private static Set<Person> mySet = new HashSet<Person>();
public static void main(String[] args) {
mySet.add(new Person("Tom","Male",170.0,70.0));
mySet.add(new Person("Peter","Male",175.0,70.0));
mySet.add(new Person("Kate","Female",168.0,60.0));
mySet.add(new Person("Alice","Female",161.0,55.0));
mySet.add(new Person("Jack","Male",190.0,95.0));
mySet.add(new Person("Jack","Male",190.0,95.0));
System.out.println(mySet);
} }
以上例子先定义了Person类,然后定义了一个HashSet,并加入了5个Person到该集合,其中1个人加入了两次,运行结果如下:

可见Jack是同一个人,却在集合中出现了两次,这是什么原因呢?这是因为,Person是Object的子类,而Object类的equals()方法是根据对象的内存地址来判断两个对象是否相等的,由于两次插入的Jack的内存地址肯定不相同,所以判断的结果是不相等,所以两次都插入了。于是,我们需要覆写equals()方法来判断两个对象是否是同一个对象。
// 覆写equals方法
public boolean equals (Object obj){
// 地址相等,则肯定是同一个对象
if(this==obj){
return true;
}
// 类型不同,则肯定不是同一类对象
if(!(obj instanceof Person)){
return false;
}
// 类型相同,向下转型
Person per=(Person) obj;
// 如果两个对象的姓名和性别相同,则是同一个人
if(this.name.equals(per.name)&&this.sex.equals(per.sex))
return true;
return false;
}
覆写equals()方法以后,运行结果如下:

可见Jack仍然被插入了两次,这是什么原因呢?这是因为Object的Hash码返回的是对象的Hash地址,而两个对象的Hash地址肯定是不相等的,所以6次插入的对象被存储在6个存储区域,equals()方法根本没有运行。于是,还需要覆写hashCode()方法,根据姓名来计算对象的Hash码。
// 覆写hashCode方法
public int hashCode(){
return this.name.hashCode();
}
运行结果如下:

可见,Jack只插入了一次,终于正确了。如果根据性别来计算对象的Hash码,结果也是正确的,Jack也只会被插入1次。但是,如果两个对象的性别不同,如下所示:
mySet.add(new Person("Jack","Male",190.0,95.0));
mySet.add(new Person("Jack","Female",190.0,95.0));
则两个对象都会被插入:

这是因为虽然两个对象的Hash码相同(不论是按照姓名,还是按照性别来计算,Hash码都是相同的),但是equals()方法判断这两个对象不相等,于是都插入了。
Java的HashSet类的更多相关文章
- JDK1.8源码(八)——java.util.HashSet 类
在上一篇博客,我们介绍了 Map 集合的一种典型实现 HashMap ,在 JDK1.8 中,HashMap 是由 数组+链表+红黑树构成,相对于早期版本的 JDK HashMap 实现,新增了红黑树 ...
- Java API —— Set接口 & HashSet类 & LinkedHashSet类
1.Set接口 1)Set接口概述 一个不包含重复元素的 collection,无序(存储顺序和取出顺序不一致),唯一. (List有序,即存储顺序和取出顺序一致,可重复) ...
- Java——(三)Collection之Set集合、HashSet类
------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- 一.Set集合 Set集合不允许包含相同的元素,如果试图把两个相同的元素加入同一个Set集合中, ...
- Java集合概述、Set集合(HashSet类、LinkedHashSet类、TreeSet类、EnumSet类)
Java集合概述.Set集合(HashSet类.LinkedHashSet类.TreeSet类.EnumSet类) 1.Java集合概述1)数组可以保存多个对象,但数组长度不可变,一旦在初始化数组时指 ...
- java——HashSet类中的常见方法
package com.xt.set; import java.util.HashSet; import java.util.Iterator; import java.util.Set; publi ...
- Java 数据类型:集合接口Collection之Set接口HashSet类;LinkedHashSet;TreeSet 类
Collection 之 Set 实现类: HashSet TreeSet 特点: 无序. 元素不可重复. (如果试图添加一个已经有的元素到一个Set集合中,那么会添失败,add()方法返回false ...
- JAVA Collections工具类sort()排序方法
主要分析内容: 一.Collections工具类两种sort()方法 二.示例 一.Collections工具类两种sort()方法 格式一: public static <T extends ...
- Java集合---Array类源码解析
Java集合---Array类源码解析 ---转自:牛奶.不加糖 一.Arrays.sort()数组排序 Java Arrays中提供了对所有类型的排序.其中主要分为Prim ...
- 【Java基础】类和接口
Num1:使类和成员的可访问性最小化 要区别设计良好的模块与设计不好的模块,最重要的因素在于,这个模块对于外部的其他模块而言,是否隐藏其内部数据和其他实现细节.设计良好的模块会隐藏所有的实现细节,把它 ...
随机推荐
- C#高级二
编程小虾米大侠之梦 软件环境:win7 开发工具:vs 2010 平台:.NET 语言:C# 类库版本:.NET Framework 2.0 语言特点:强类型语言 规划知识点: 1..net fram ...
- 元素设置为display:none,其绑定的事件仍存在
元素设置为display:none,虽然该元素从页面中消失了,其绑定的事件仍存在. <body> <button class="button1">chang ...
- java基础之集合框架
6.集合框架: (1)为什么出现集合类? 面向对象对事物的体现都是以对象的形式,为了方便对多个对象的操作,就对对象进行存储. 集合就是存储对象最常用的一种方式. (2)数组和集合都是容器,两者有何不同 ...
- EF架构~二级域名中共享Session
回到目录 对于一个有点规模的网站,都会有各个子网站,说是子网站,其实也都是独立的站点,一般通过二次域名来分开,如www.zzl.com,它可以有很多子网站,如image.zzl.com,file.zz ...
- display的理解
display可把框内显示的内容改变(自我理解) none 此元素不会被显示. block 此元素将显示为块级元素,此元素前后会带有换行符. inline 默认.此元素会被显示为内联元素,元素前后没有 ...
- Atitit 信用卡与会员卡(包括银行卡)的发展之路
Atitit 信用卡与会员卡(包括银行卡)的发展之路 实现跨机构卡片内金额的流动解决方案 1.1. 财务卡片本质上都是会员卡1 1.2. 卡片的发展阶段1 2. 实现跨机构卡片内金额的流动解决方案(加 ...
- 发现一个百度的密码。。。记最近一段时间的php感想
请看图. 突然想看一下百度的cookie. 最近百度一年真是多攒多难,我一直挺百度啊.百度文化就是程序员文化,但是收到中国其他文化的侵蚀,不得不变, 任何人重构系统,都会有大概百分三十左右的性能提升. ...
- SpringMVC与mybatis整合
一.逆向工程生成基础信息 <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE generator ...
- 【WP 8.1开发】如何处理摄像头翻转的问题
模拟器就像我们儿时的梦境,在其上运行应用程序时,一切总是那么美好的:而真机测试如同我们这个纷乱无章的现实世界,你会遇到各种小人和畜生,常常会遭受莫名的挫折.面对挫折,有人迎难而上,或不予理采,走自己的 ...
- CSS选择器、CSS hack及CSS执行效率
主要内容: 1.CSS选择器.优先级与匹配原理 2. CSS 引入的方式有哪些 ? link 和 @import 的区别是 ? 3.CSS hack 4.如何书高效CSS 一.CSS选择器.优先级与 ...