31.1 Set 接口基本介绍
- 无序(添加和取出的顺序不一致),没有索引
- 不允许重复元素,所以最多包含一个 null
31.2 Set 接口的常用方法
和 List 接口一样,Set 接口也是Collection 的子接口,因此,常用方法和Collection接口一样
31.3 Set 接口的遍历方式
- 可以使用迭代器
- 增强 for
- 不能使用 索引的方式来获取
31.4 HashSet
- HashSet 实现了 Set 接口
- HashSet 实际上是 HashMap
public HashSet() {
map = new HashMap<>();
}
- 可以存放 Null 值,但是只能有一个Null
- HashSet 不保证元素是有序的,取决于hash后,再确定索引的结果(即不保证存放元素的顺序和取出顺序一致)
- 不能重复元素/对象
31.5 HashSet 底层机制说明
- HashSet 底层是 HashMap
- 添加一个元素时,先得到 Hash 值(会转成 -> 索引值)
- 找到存储数据表 table,看这个索引位置是否已经存放过元素
- 如果没有,直接加入
- 如果有,调用 equals 比较(可重写方法),如果相同,就放弃添加,如果不相同,则以链表的形式添加到该索引对应的已有元素最后面
- 在 java8 中,如果一条链表的元素个数到达
TREEIFY_THRESHOLD
(默认是 8),并且 table 的大小 >=MIN_TREEIFY_CAPACITY
(默认 64),就会进行树化(红黑树)
31.6 LinkedHashSet
- LinkedHashSet 是 HashSet 的子类
- LinkedHashSet 底层是一个 LinkedHashMap,底层维护了一个 数组+双向链表
- LinkedHashSet 根据元素的 HashCode 值来决定元素的存储位置,同时使用链表维护元素的次序,这使得元素看起来是以 插入顺序保存 的
- 不允许添加重复元素