对于 HashSet 而言,它是基于 HashMap 实现的,HashSet 底层采用 HashMap 来保存所有元素,因此 HashSet 的实现比较简单,查看 HashSet 的源代码,可以看到如下代码:
public class HashSet<E>
extends AbstractSet<E>
implements Set<E>, Cloneable, java.io.Serializable
{
// 使用 HashMap 的 key 保存 HashSet 中所有元素
private transient HashMap<E,Object> map;
// 定义一个虚拟的 Object 对象作为 HashMap 的 value
private static final Object PRESENT = new Object();
...
// 初始化 HashSet,底层会初始化一个 HashMap
public HashSet()
{
map = new HashMap<E,Object>();
}
// 以指定的 initialCapacity、loadFactor 创建 HashSet
// 其实就是以相应的参数创建 HashMap
public HashSet(int initialCapacity, float loadFactor)
{
map = new HashMap<E,Object>(initialCapacity, loadFactor);
}
public HashSet(int initialCapacity)
{
map = new HashMap<E,Object>(initialCapacity);
}
HashSet(int initialCapacity, float loadFactor, boolean dummy)
{
map = new LinkedHashMap<E,Object>(initialCapacity
, loadFactor);
}
// 调用 map 的 keySet 来返回所有的 key
public Iterator<E> iterator()
{
return map.keySet().iterator();
}
// 调用 HashMap 的 size() 方法返回 Entry 的数量,就得到该 Set 里元素的个数
public int size()
{
return map.size();
}
// 调用 HashMap 的 isEmpty() 判断该 HashSet 是否为空,
// 当 HashMap 为空时,对应的 HashSet 也为空
public boolean isEmpty()
{
return map.isEmpty();
}
// 调用 HashMap 的 containsKey 判断是否包含指定 key
//HashSet 的所有元素就是通过 HashMap 的 key 来保存的
public boolean contains(Object o)
{
return map.containsKey(o);
}
// 将指定元素放入 HashSet 中,也就是将该元素作为 key 放入 HashMap
public boolean add(E e)
{
return map.put(e, PRESENT) == null;
}
// 调用 HashMap 的 remove 方法删除指定 Entry,也就删除了 HashSet 中对应的元素
public boolean remove(Object o)
{
return map.remove(o)==PRESENT;
}
// 调用 Map 的 clear 方法清空所有 Entry,也就清空了 HashSet 中所有元素
public void clear()
{
map.clear();
}
...
}
由上面源程序可以看出,HashSet 的实现其实非常简单,它只是封装了一个 HashMap 对象来存储所有的集合元素,所有放入 HashSet 中的集合元素实际上由 HashMap 的 key 来保存,而 HashMap 的 value 则存储了一个 PRESENT,它是一个静态的 Object 对象。
HashSet 的绝大部分方法都是通过调用 HashMap 的方法来实现的,因此 HashSet 和 HashMap 两个集合在实现本质上是相同的。
HashMap 的 put 与 HashSet 的 add
由于 HashSet 的 add() 方法添加集合元素时实际上转变为调用 HashMap 的 put() 方法来添加 key-value 对,当新放入 HashMap 的 Entry 中 key 与集合中原有 Entry 的 key 相同(hashCode() 返回值相等,通过 equals 比较也返回 true),新添加的 Entry 的 value 将覆盖原来 Entry 的 value,但 key 不会有任何改变,因此如果向 HashSet 中添加一个已经存在的元素,新添加的集合元素(底层由 HashMap 的 key 保存)不会覆盖已有的集合元素。
掌握上面理论知识之后,接下来看一个示例程序,测试一下自己是否真正掌握了 HashMap 和 HashSet 集合的功能。
主要说明的就是重写equals()方法时,就必须重写hashCode()方法。
class Name
{
private String first;
private String last;
public Name(String first, String last)
{
this.first = first;
this.last = last;
}
public boolean equals(Object o)
{
if (this == o)
{
return true;
}
if (o.getClass() == Name.class)
{
Name n = (Name)o;
return n.first.equals(first)
&& n.last.equals(last);
}
return false;
}
}
public class HashSetTest
{
public static void main(String[] args)
{
Set<Name> s = new HashSet<Name>();
s.add(new Name("abc", "123"));
System.out.println(
s.contains(new Name("abc", "123")));
}
}
上面程序中向 HashSet 里添加了一个 new Name("abc", "123") 对象之后,立即通过程序判断该 HashSet 是否包含一个 new Name("abc", "123") 对象。粗看上去,很容易以为该程序会输出 true。
实际运行上面程序将看到程序输出 false,这是因为 HashSet 判断两个对象相等的标准除了要求通过 equals() 方法比较返回 true 之外,还要求两个对象的 hashCode() 返回值相等。而上面程序没有重写 Name 类的 hashCode() 方法,两个 Name 对象的 hashCode() 返回值并不相同,因此 HashSet 会把它们当成 2 个对象处理,因此程序返回 false。
由此可见,当我们试图把某个类的对象当成 HashMap 的 key,或试图将这个类的对象放入 HashSet 中保存时,重写该类的 equals(Object obj) 方法和 hashCode() 方法很重要,而且这两个方法的返回值必须保持一致:当该类的两个的 hashCode() 返回值相同时,它们通过 equals() 方法比较也应该返回 true。通常来说,所有参与计算 hashCode() 返回值的关键属性,都应该用于作为 equals() 比较的标准。
如下程序就正确重写了 Name 类的 hashCode() 和 equals() 方法,程序如下:
class Name
{
private String first;
private String last;
public Name(String first, String last)
{
this.first = first;
this.last = last;
}
// 根据 first 判断两个 Name 是否相等
public boolean equals(Object o)
{
if (this == o)
{
return true;
}
if (o.getClass() == Name.class)
{
Name n = (Name)o;
return n.first.equals(first);
}
return false;
}
// 根据 first 计算 Name 对象的 hashCode() 返回值
public int hashCode()
{
return first.hashCode();
}
public String toString()
{
return "Name[first=" + first + ", last=" + last + "]";
}
}
public class HashSetTest2
{
public static void main(String[] args)
{
HashSet<Name> set = new HashSet<Name>();
set.add(new Name("abc" , "123"));
set.add(new Name("abc" , "456"));
System.out.println(set);
}
}
上面程序中提供了一个 Name 类,该 Name 类重写了 equals() 和 toString() 两个方法,这两个方法都是根据 Name 类的 first 实例变量来判断的,当两个 Name 对象的 first 实例变量相等时,这两个 Name 对象的 hashCode() 返回值也相同,通过 equals() 比较也会返回 true。
程序主方法先将第一个 Name 对象添加到 HashSet 中,该 Name 对象的 first 实例变量值为"abc",接着程序再次试图将一个 first 为"abc"的 Name 对象添加到 HashSet 中,很明显,此时没法将新的 Name 对象添加到该 HashSet 中,因为此处试图添加的 Name 对象的 first 也是" abc",HashSet 会判断此处新增的 Name 对象与原有的 Name 对象相同,因此无法添加进入,程序在①号代码处输出 set 集合时将看到该集合里只包含一个 Name 对象,就是第一个、last 为"123"的 Name 对象。
以上所述是小编给大家介绍的HashSet工作原理_动力节点Java学院整理,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对网站的支持!
# hashset原理
# hashset的工作原理
# java
# java中HashSet的特点及实例用法
# Java HashSet集合存储遍历学生对象代码实例
# Java面试题之HashSet的实现原理
# 通过实例学习Java集合框架HashSet
# java 中HashMap、HashSet、TreeMap、TreeSet判断元素相同的几种方法比较
# 浅析Java中Map与HashMap
# Hashtable
# HashSet的区别
# Java基础之详解HashSet的使用方法
# 返回值
# 重写
# 这两个
# 都是
# 为空
# 第一个
# 也就
# 它是
# 写了
# 小编
# 到该
# 有任何
# 也会
# 在此
# 很容易
# 给大家
# 很重要
# 可以看到
# 就得
# 可以看出
相关文章:
,在苏州找工作,上哪个网站比较好?
建站中国官网:模板定制+SEO优化+建站流程一站式指南
移动端手机网站制作软件,掌上时代,移动端网站的谷歌SEO该如何做?
邀请函制作网站有哪些,有没有做年会邀请函的网站啊?在线制作,模板很多的那种?
简单实现Android文件上传
可靠的网站设计制作软件,做网站设计需要什么样的电脑配置?
电脑免费海报制作网站推荐,招聘海报哪个网站多?
香港服务器网站生成指南:免费资源整合与高速稳定配置方案
香港服务器部署网站为何提示未备案?
无锡营销型网站制作公司,无锡网选车牌流程?
淘宝制作网站有哪些,淘宝网官网主页?
,怎么用自己头像做动态表情包?
山东网站制作公司有哪些,山东大源集团官网?
建站主机选哪家性价比最高?
如何在服务器上配置二级域名建站?
宠物网站制作html代码,有没有专门介绍宠物如何养的网站啊?
图片制作网站免费软件,有没有免费的网站或软件可以将图片批量转为A4大小的pdf?
广州美橙建站如何快速搭建多端合一网站?
重庆市网站制作公司,重庆招聘网站哪个好?
如何设计高效校园网站?
娃派WAP自助建站:免费模板+移动优化,快速打造专业网站
如何高效利用亚马逊云主机搭建企业网站?
如何通过网站建站时间优化SEO与用户体验?
天河区网站制作公司,广州天河区如何办理身份证?需要什么资料有预约的网站吗?
C#如何序列化对象为XML XmlSerializer用法
定制建站哪家更专业可靠?推荐榜单揭晓
c# 服务器GC和工作站GC的区别和设置
PHP正则匹配日期和时间(时间戳转换)的实例代码
mc皮肤壁纸制作器,苹果平板怎么设置自己想要的壁纸我的世界?
西安市网站制作公司,哪个相亲网站比较好?西安比较好的相亲网站?
如何用狗爹虚拟主机快速搭建网站?
XML的“混合内容”是什么 怎么用DTD或XSD定义
如何在IIS中新建站点并配置端口与物理路径?
C++如何将C风格字符串(char*)转换为std::string?(代码示例)
如何处理“XML格式不正确”错误 常见XML well-formed问题解决方法
太原网站制作公司有哪些,网约车营运证查询官网?
油猴 教程,油猴搜脚本为什么会网页无法显示?
设计网站制作公司有哪些,制作网页教程?
高配服务器限时抢购:企业级配置与回收服务一站式优惠方案
如何基于PHP生成高效IDC网络公司建站源码?
高端智能建站公司优选:品牌定制与SEO优化一站式服务
如何用西部建站助手快速创建专业网站?
南京网站制作费用,南京远驱官方网站?
网站制作新手教程,新手建设一个网站需要注意些什么?
建站主机如何选?性能与价格怎样平衡?
公司网站建设制作费用,想建设一个属于自己的企业网站,该如何去做?
网站专业制作公司,网站编辑是做什么的?好做吗?工作前景如何?
北京建设网站制作公司,北京古代建筑博物馆预约官网?
建站之星客服服务时间及联系方式如何?
如何快速选择适合个人网站的云服务器配置?
*请认真填写需求信息,我们会在24小时内与您取得联系。