集合4、集合_Collection接口_Set接口
Set接口的使用
存储无序的、不可重复的数据
三种实现类:
- HashSet:作为Set接口的主要实现类;线程不安全;可以存储 null 值
- LinkedHashSet:作为HashSet的子类;遍历其内部数据时,可以按照添加的顺序遍历;对于频繁的遍历操作,LinkedHashSet的效率比HashSet高
- TreeSet:可以按照添加对象的指定属性,进行排序
注:1. Set接口中没有额外定义新的方法,使用的都是Collection中声明过的方法
2. 向Set中添加的数据,其所在类一定要重写hashCode()和equals()且重写的hashCode()和equals()尽可能保持一致:相等的对象具有相等的散列码
一、理解无序性与不可重复性
以HashSet为例说明
- 无序性:不等于随机性。存储的数据在底层数组中并非按照数组索引的顺序添加,而是根据数据的哈希值决定的
- 不可重复性:保证添加的元素按照equals()判断时,不能返回true:即相同的元素只能添加一个
二、Set中添加元素的过程(以HashSet为例)
我们向HashSet中添加元素 a,首先调用元素 a 所在类的hashCode()方法,计算元素 a 的哈希值,此哈希值接着通过某种算法计算出在HashSet底层数组中存放的位置(即:索引位置),判断数组此位置上是否有元素:
- 如果此位置上没有其他元素,则元素 a 添加成功。
- 如果此位置上有其他元素 b(或以链表形式存在多个元素),则比较元素 a 与元素 b 的哈希值:
- 如果哈希值不相同,则 a 元素添加成功------>情况2
- 如果哈希值相同,则进而需要调用元素 a 所在类的equals()方法:
- equals()返回true,元素 a 添加失败
- equals()返回false,则元素 a 添加成功------>情况3
对于添加成功的情况2与情况3而言,元素 a 与已经存在指定索引位置上的数据以链表的方式存储。
jdk7:元素 a 放到数组中,指向原来的元素
jdk8:原来的元素在数组中,指向元素 a
总结:七上八下
HashSet底层结构:数组+链表
三、LinkedHashSet
遍历的时候,按照添加的顺序遍历
LinkedHashSet作为HashSet的子类,在添加数据的同时,每个数据还维护了两个引用,记录此数据的前一个数据和后一个数据(双向链表):
优点:对于频繁的遍历操作,LinkedHashSet的效率比HashSet高
四、TreeSet
- 向TreeSet中添加的数据,要求是相同类的对象
- 两种排序方法:自然排序(实现Comparable接口)、定制排序(Comparator)
- 自然排序中,比较两个对象是否相同的标准为:compareTo()返回0,不再是equals()
- 定制排序中,比较两个对象是否相同的标准为:compara()返回0,不在是equals()

浙公网安备 33010602011771号