set集合
Set系列集合:
无序:存取顺序不一致
不重复:可以去除重复
无索引:没有带索引的方法,所以不能使用普通for循环遍历,也不能通过索引来获取元素
可以看出set是无序的存和打印的顺序不一样
Set接中的方法上基本上与Collection的APl一致:
小练习:
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.function.Consumer;public class text9 {public static void main(String[] args) {Set<String> s= new HashSet<String>();s.add("张三");s.add("李四");s.add("张三");s.add("王五");//迭代器遍历Iterator<String> it=s.iterator();while(it.hasNext()){System.out.println(it.next());}//增强for循环遍历for(String str:s ){System.out.println(str);}//Lambda表达式遍历s.forEach(str-> System.out.println(str));}
}
小结:
1. Set系列集合的特点
- 无序、不重复、无索引
- Set集合的方法上基本上与Collection的APl一致
2.Set集合的实现类特点
- HashSet 无序、不重复、无索引
- LinkedHashSet:有序、不重复、无索引
- TreeSet:可排序、不重复、无索引
set集合中实现类HashSet
HashSet底层原理
- HashSet集合底层采取哈希表存储数据
- 哈希表是一种对于增删改查数据性能都较好的结构
哈希表组成
- JDK8之前: 数组+链表
- JDK8开始: 数组+链表+红黑树
哈希值
- 根据hashCode方法算出来的int类型的整数
- 该方法定义在Object类中,所有对象都可以调用,默认使用地址值进行计算
- 一般情况下,会重写hashCode方法,利用对象内部的属性值计算哈希值
对象的哈希值特点
- 如果没有重写hashCode方法,不同对象计算出的哈希值是不同的
- 如果已经重写hashcode方法,不同的对象只要属性值相同,计算出的哈希值就是一样的
- 在小部分情况下,不同的属性值或者不同的地址值计算出来的哈希值也有可能一样。 (哈希碰撞)
没有重写hashCode打印的结果
重写hashCode打印的结果
在对象中重写hashCode方法alt+inset idea会自动生成
哈希碰撞
HashSet 底层原理
哈希表组成
- JDK8之前: 数组+链表
- JDK8开始: 数组+链表+红黑树
加载因子:是用来数组的扩容的
JDK8以后,当链表长度超过8,而且数组长度大于等于64时 自动转换为红黑树
如果集合中存储的是自定义对象,必须要重写hashCode和equals方法
string Integer 在HashSet中不需要重写方法因为这俩类已经重写好了。
LinkedHashSet底层原理
- 有序、不重复、无索引。
- 这里的有序指的是保证存储和取出的元素顺序一致
- 原理:底层数据结构是依然[ 哈希表 只是每个元素又额外的多了一个 双链表的机制记录存储的顺序。
在以后如果要数据去重,我们使用哪个?
默认使用HashSet
如果要求去重且存取有序,才使用L LinkedHashSet :因为效率比较低
TreeSet
默认排序/自然排序:Javabean类实现Comparable接口指定比较规则
TreeSet的特点
- 不需要重写hashcode和equals方法因为TreeSet的底层是红黑树,但是要指定排序规则
- 不重复、无索引、可排序
- 可排序:按照元素的默认规则(有小到大)排序。
- TreeSet集合底层是基于红黑树的数据结构实现排序的,增删改查性能都较好。
可排序代码案例:
打印结果:
三种遍历:
打印结果:
重写排序规则的理解:
TreeSet第二种排序
比较字符串默认是按首字母大小来排序的,如果我们想先按长度进行排序如果长度一样再按首字母排序。就会用到第二中排序方式。
比较器排序:创建TreeSet对象时候,传递比较器Comparator指定规则
使用原则:默认使用第一种,如果第一种不能满足当前需求,就使用第二种
查看API文档找treeset 利用接口new comparator<String>重写compare方法
代码案例
练习