#博学谷IT学习技术支持#
本周的内容主要是Set和Map集合,Set是单列集合,每个值以键的方式存储,而Map是双列集合,以键值对的方式存储。
Set是一个接口,实现Set集合的类有三个特点:
TreeSet是Set接口的一个实现类,该实现类具备Set接口的三个特点,由于Set集合会进行排序,若没有指定排序规则,即类需要实现Comparable接口或者使用匿名内部类,指定排序顺序,否则执行代码时会出现异常。
异常介绍:存在一个Student类,该类未实现Comparable接口,将类的对象添加到TreeSet集合中,运行时出现了ClassCastException异常
指定排序顺序有两种方式:类实现Comparable接口、使用Comparator比较器指定排序方式
执行原理:数据添加到TreeSet集合前,根据指定的排序逻辑,判断本次添加的数据的存储位置,若compareTo方法的返回值>0,说明本次添加的数据比较大,存在已存在数据的右边,反之则存在左边,等于0则不进行存储。
Student类实现Comparable接口并重写compareTo方法,从代码来看,将Student类存储到TreeSet集合中时,将会按照学生年龄从小到大进行排序,若写法改为返回"o.age -this.age",则按照从大到小排序。
使用匿名内部类传递Comparator比较器,指定排序顺序
创建TreeSet对象时,指定学生年龄从小到大进行排序
使用Lambda表达式指定排序顺序
按照以上两种排序方式存储数据,创建三个学生对象,其年龄分别为15,35,20,存储后的顺序为:
HashSet底层数据结构为哈希表,其关键为哈希值,是JDK按照对象的地址或属性值算出来的值,若对象类重写了HashCode方法,则按照重写的方法获取哈希值。
哈希表在JDK8之前底层采用“数组+链表”的方式实现,而在JDK8之后为了提高数据的添加效率,调整为“数组+链表+红黑树”。
数组长度默认为16,加载因子为0.75,即数组中若已存满16*0.75=12个元素时,数组会进行扩容,长度变为原来的两倍。
存储步骤:
(1)获取元素的哈希值,计算出该值在数组中应存入的位置
(2)判断数组对应位置是否为null
(3)若为null,则直接将该值添加到对应位置
(4)若不为null,并且该值与之前已存储的数据不同,则添加进对应位置的链表(红黑树)中
JDK8之前与之后存储数据的差别在于JDK8之后增加了红黑树,数组中存储数据的链表长度默认为8,若该位置存储的长度已为8,那么下次再添加数据时自动由链表改为红黑树。
Set和Map集合差异不大,在于Set为单列集合,Map为双列集合,Set以键方式存储,而Map以键值对(Entry对象)存储,所以Map相关的知识点都是与Set类似,Set接口的实现类有TreeSet和HashSet,将这两个类中的Set改为Map,就变成了Map接口的实现类。