Set接口的集合实现类
Set接口的基本介绍
- 无序(取出和添加的顺序不一致),没有索引
- 不允许重复元素,所以最多包含一个null
- 常用的实现类有HashSet、TreeSet、LinkedHashSet
- 注:虽然存放和取出的顺序不一样,但是集合内的顺序是固定的
常用方法
- 常用方法和List子接口的方法一样
- 遍历方式可以选择增强for循环、迭代器,但是不能通过索引的方式获取。
HashSet
特点
- HashSet的底层是一个HashMap<>;HashMap底层是(数组+链表+红黑树)
- 可以存放null值,但是只能有一个null;
- HashSet不保证元素是有序的(取出和存放顺序不一定一样),取决于hash后,确定索引的结果;
- 不能有重复元素/对象。
HashSet执行流程
- 添加一个元素时,先得到hash值,hash值转换成索引值
- 找到存储数据的table,查看索引位置是否存在值
- 如果没有直接加入,如果存在,比较内容是否相同(equals),如果相同,则放弃添加,如果不同,则添加到最后
- 在jdk8中,如果一条链表的元素个数大于等于八个并且table的大小大于等于64,就会转换成一条红黑树。
- 在HashSet中,首先获取hashcode,如果hashcode相同再比较equals(),当这两个值都相同时,才能确定两个元素是相同的目的。
LinkedHashSet
- 继承了HashSet类
- LinkedHashSet底层是一个LinkedHashMap,底层维护了一个数组+双向链表
- LinkedHashSet根据元素的hashCode值来决定元素的存储位置,同时使用链表维护元素的次序,是的元素看起来是以插入顺序保存的。
- LinkedHashSet不允许添加重复元素。
- 其table的扩容机制和HashSet的扩容方式相同。
说明
- LinkedHashSet维护了一个hash表和双向链表:LinkedHashSet中有head和tail。head指向所有元素的第一个元素,tail指向所有元素的最后一个元素。
- 每一个节点都有before和after属性
- 添加元素时先求hash,再求索引,确定元素在table中的位置,当且仅当元素的hash值和equals内容相同时,不能添加进去。
- LinkedHashSet保证了在插入和删除时顺序一致。