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:使类和成员的可访问性最小化 要区别设计良好的模块与设计不好的模块,最重要的因素在于,这个模块对于外部的其他模块而言,是否隐藏其内部数据和其他实现细节.设计良好的模块会隐藏所有的实现细节,把它 ...
随机推荐
- 爱上MVC~MVC4模型验证可以放在前端
回到目录 MVC4.0推出后,在模型验证上有了一个新的改近,它支持前端验证,即在用户POST之前,如果验证失败,则Action(POST方式的)不会被执行,而直接停留在原视图,这对于用户体验是好的,它 ...
- Mybatis的缺陷
Mybatis是业界非常流行的持久层框架,轻量级.易用,在金融IT领域完全是领军地位,比Hibernate更受欢迎,优势非常多,也是非常值得我们学习的.但Mybatis并不尽善尽美,其自身的设计.编码 ...
- 贪心算法-最小生成树Kruskal算法和Prim算法
Kruskal算法: 不断地选择未被选中的边中权重最轻且不会形成环的一条. 简单的理解: 不停地循环,每一次都寻找两个顶点,这两个顶点不在同一个真子集里,且边上的权值最小. 把找到的这两个顶点联合起来 ...
- PHP将富文本编辑后的内容,去除样式图片等只保留txt文本内容
1.从数据库读取富文本内容样式如下: <p style=";text-indent: 0;padding: 0;line-height: 26px"><span ...
- 通过shape-outside来设置文字环绕时的形状
现在真是越来越注重用户体验了,而"shape-outside"就是其中一个能让网页排版更友好的一个属性. 默认文字是根据图片的边进行的. 但现在我们完全有能力去改变这一行为,下面是 ...
- 真正的mybatis_redis二级缓存
网上流传的代码缓存失效存在严重问题. 思路....以后再细说 目前的方案还不够完美,失效力度控制不够细. 主要代码 import java.io.BufferedReader; import java ...
- struts2默认action
struts.xml文件的某个package中添加<default-action-ref name="error"></default-action-ref> ...
- 深入理解CSS溢出overflow
× 目录 [1]定义 [2]属性 [3]失效[4]应用 前面的话 当一个元素固定为某个特定大小,但内容在元素中放不下.此时就可以利用overflow属性来控制这种情况 定义 overflow溢出 值: ...
- sublime简要笔记
选中单词 [1]选中当前单词 ctrl+d [2]跳过当前单词 ctrl+k ctrl+d [3]选中相同的所有单词 alt+f3 [4]多行游标 按住shift,然后按住鼠标右键向下拖动 行操作 [ ...
- 构建自己的PHP框架--搭建基本结构
首先,我们来说一下,为什么要创建自己的框架? 为什么要创建自己的框架呢?如果你跟周围的人讨论,每个人都会告诉你重复发明轮子是一件糟糕的事情,你最好选择一个已有的框架,忘掉“创建自己的框架”这种想法.大 ...