LinkedHashSet的原理
之前我们了解到LinkedHashSet的特点:
- 有序、不重复、无索引
它的底层原理
- 依然是基于哈希表(数组、链表、红黑树)实现的。
- 但是,它的每个元素都额外的多了一个双链表的机制记录它前后元素的位置。
当有要填入的元素的哈希值一样时:
同时,双链表的机制代表着它有着头指针与尾指针,分别指向第一个元素和最后一个元素:
TreeSet集合
介绍
- 特点:不重复、无索引、可排序(默认升序排序,按照元素的大小,由小到大排序)
- 底层是基于红黑树实现的排序。
import java.util.Set; import java.util.TreeSet; public class SetDemo4 { public static void main(String[] args) { Set<Integer> integerSet = new TreeSet<>(); integerSet.add(135); integerSet.add(13); integerSet.add(113); integerSet.add(255); integerSet.add(255); System.out.println(integerSet); } }
运行结果:
注意:
- 对于数值类型:Integer,Double,默认按照数值本身的大小进行升序排序。
- 对于字符串类型:默认按照首字符的编号升序排序。
- 对于自定义类型如Student对象,TreeSet默认是无法直接排序的。
例如:
1. imimport java.util.Set; import java.util.TreeSet; public class SetDemo4 { public static void main(String[] args) { Set<Student> students = new TreeSet<>(); students.add(new Student("至尊宝",26,165.5)); students.add(new Student("蜘蛛精",23,169.7)); students.add(new Student("牛魔王",22,183.5)); students.add(new Student("紫霞",22,169.8)); System.out.println(students); } }
运行报错:
这时就需要用到我们熟悉的自定义排序规则了,
自定义排序规则
- TreeSet集合存储自定义类型的对象时,必须指定排序规则,支持如下两种方式来指定比较规则。
方式一
让自定义的类(如学生类)实现Comparable接口,重写里面的compareTo方法来指定比较规则。
方式二
通过调用TreeSet集合有参数构造器,可以设置Comparator对象(比较器对象,用于指定比较规则)。
public TreeSet(Comparator<? super E> comparator)
排序示例
第一种自定义排序方式:让类实现Comparable接口,并重写里面的compareTo方法
此时再运行一次代码,得到结果:
按年龄升序排序,其中有两个年龄相同的对象,重复的不进行存储。
第二种自定义排序方式:调用TreeSet集合有参数构造器,设置Comparator对象
当两种自定义排序都存在时,TreeSet会就近选择自己自带的比较器对象进行排序
运行结果:
因为身高没有重复的,所以都存储进去了。
Lambda简化
最后回顾总结一下,两种方式中,关于返回值的规则:
- 如果认为第一个元素>第二个元素返回正整数即可。
- 如果认为第一个元素<第二个元素返回负整数即可。
- 如果认为第一个元素=第二个元素返回o即可,此时Treeset集合只会保留一个元素,认为两者重复。
- 注意:如果类本身有实现Comparable接口,TreeSet集合同时也自带比较器,默认使用集合自带的比较器排序。
END