java hashset 实现_跟我学Java编程—Set接口实现类HashSet

Set接口是Collection的子接口。Set接口存放的元素是无序的且不包含重复的元素,类似于数学概念的集合,集合中不允许有重复元素。Set接口有三个常用的实现类,分别是HashSet、LinkedHashSet、TreeSet,本节主要介绍HashSet实现类。

HashSet是Set接口实现类之一,使用较为广泛,它不保存元素的加入顺序,并且不允许存储重复的元素。也就是当容器中已经存储一个相同的元素时,无法再添加一个完全相同的元素。

下面先通过一个应用实例对HashSet的用法有个具体了解。

a9bb31ff52f0013c14b52d4fc45ca8be.png

例子代码声明并实例化了一个HashSet对象,HashSet存储的元素是String对象,然后通过HashSet的add方法添加String对象,最后通过Iterator迭代器遍历HashSet集合。

运行上述程序,在控制台上显示效果如下图所示:

b3cf2ae78c2203ade29d555b7e158dd9.png图 14-3 HashSetTest输出结果

从上图可以看出,HashSet添加的顺序与迭代显示的结果顺序并不一致,这也验证了HashSet存储元素的无序特征。有的同学可能会问,前面学过的数组、上节中例子代码的ArrayList都与加入元素的顺序相关,为什么HashSet与加入的元素顺序无关了呢?

其实,HashSet类是根据元素的哈希码进行存储的,HashSet根据每个存储对象的哈希码值(调用hashCode方法获得),用固定的算法算出它的存储索引,把存储对象存放在一个叫做散列表的相应位置中,如果对应的位置没有其它元素,就只需要直接存入;如果该位置已经有元素了,就会将新对象跟该位置的所有对象进行比较(调用equals()方法),以查看容器中是否已经存在该对象,若不存在,就存放该对象,若已经存在,就直接使用该对象。

36e9a6ab347ba900139dd38b6973bbc4.png图 14-4 HashSet存储结构

HashSet的存储结构是个链表数组,每一个数组元素就是一个链表,类似这种数据结构称为散列表。上图中左边是数组,用于存储元素,该存储元素对应的数组下标是调用hashCode方法返回的存储元素的哈希码。当后加入元素的哈希码与已经加入的元素哈希码相同时,HashSet就会创建一个链表,将相同哈希码的元素存入一个链表,并将该链表的头指针存储到哈希码对应的数组元素中。

前面的示例只是添加了String对象,如果要添加一个自定义的对象,又该如何呢?

用HashSet存储自定义对象的用法。

a1dbce2ebfe1b4098e663be609e78f43.png

因为Set集合中不能加入重复的元素,所以对于自定义类,需要提供判断怎样才算重复元素的方法。在例子代码中,hashCode()和equals()方法即是用来判断RemoveDuplicateObj对象是否为重复对象的标准方法。

equals()方法用来比较两个对象是否为相等的对象。在自己实现的equals()方法中,用相关的条件来进行比较。例如对于RemoveDuplicateObj类,这里用name属性进行比较,name属性相同的为相等对象。

hashCode()方法是用来在散列存储结构中确定对象的存储地址的,两个对象的hashCode相同,并不一定表示两个对象就相同,只能够说明这两个对象在散列存储结构中,存储在在同一个链表中。Java初学者可以这样理解,hashCode()方法实际上返回的就是对象存储的物理地址(实际可能并不是,而是一个与对象相关的值)。 当集合要添加新的元素时,先调用这个元素的hashCode方法,就一下子能定位到它应该放置的物理位置上。

■ 知识点拨

Set实现类取对象时根据对象和哈希吗值计算出该对象的存储索引,在散列表相应位置上的元素间进行少量的比较操作就可以找到。Set接口存、取、删对象都有很高的效率。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值