Set接口和常用方法
基本介绍
- 无序(添加和取出的顺序不一致),没有索引(不可以通过索引获取其中的元素)
- 不允许从复元素,所以最多包含一个null
- JDK API中Set接口的实现类有:HashSet、TreeSet等
- Set接口的常用方法:和List一样,Set接口也是Collection的子接口,因此,常用方法和COllection接口一样
- Set接口的遍历方式
1.可以使用迭代器
2.增强for
3.不能使用索引的方式来获取
HashSet的全面说明
- HashSet实现了Set接口
- HashSet实际上是HashMap
- 可以存放null只,但是只有一个null
- HashSet不保证元素是有序的,取决hash后,再确定索引的结果
- 不能有从复元素/对象
HashSet底层机制说明
- HashSet底层是一个HashMap
- 添加一个元素时,先的到hash值然后会转成->索引值
- 找到存储数据表table,看这个索引位置是否已经存放的有元素
- 如果没有直接加入
- 如果有,调用equals比较,如果相同,就放弃添加,如果不相同,则添加到最后。equals方法可以由自己决定,可以进行重写
- 在Java8中,如果一条链表的元素个数到达 TREEIFY_THRESHOLD(默认是8),并且table的大小 >= MIN_TERRIFY_CAPACITY(默认64),就会进行树化(红黑树);如果一条链表元素个数到8,单table没到64,就会先对table进行扩容
分析HashSet的扩容和转成红黑树机制
- HashSet底层是HashMap,第一次添加时,table数组扩容到16,临界值(threshold)是16*加载因子(loadFactor)是0.75 = 12
- 如果table数组使用到了临界值12,就会扩容到16 * 2=32,新的临界值就是32*0.75=24,依次类推
- 在Java8中,如果一条链表的元素个数到达 TREEIFY_THRESHOLD(默认是8),并且table的大小 >= MIN_TREEIFY_CAPACITY(默认64),就会进行树化(红黑树),否则仍然采用数组的扩容机制
LinkedHashSet的全面说明
- LinkedHashSet是HashSet的子类
- LinkedHashSet底层是一个LinkedHashMap底层维护了一个 数组 + 双向链表
- LinkedHashSet根据元素的hashCode值来决定元素的存储位置,同时使用链表维护元素的次序,这使得元素看起来是以插入顺序保存的
- LinkedHashSet不允许添加从复元素
说明
- 在LinkedHashSet 中维护了一个hash表和双向链表(LinkedHashSet有head和tail)
- 每一个节点有pre和next属性,这样可以形成双向链表
- 在添加一个元素时,先求hash值,在求索引,确定该元素在hashtable的位置,然后将添加的元素加入到双向链表(如果已经存在,不添加[原则和hashset一样])
- 这样的话,我们遍历LinkedHashSet也能确保插入顺序和遍历顺序一致
解读
- LinkedHashSet 加入顺序和取出元素/数据的顺序一致
- LinkedHashSet 底层维护的是一个LinkedHashMap(是HashMap的子类)
- LinkedHashSet 底层结构(数组table+双向链表)
- 添加第一次时,直接将数组table扩容到 16 ,存放的节点类型是LinkedHashMap$Entry
- 数组是HashMap N o d e [ ] 存放的元素 / 数据是 L i n k e d H a s h M a p Node[] 存放的元素/数据是LinkedHashMap Node[]存放的元素/数据是LinkedHashMapEntry