java集合框架之TreeSet类

来源:互联网 发布:中国移动 plmn 网络id 编辑:程序博客网 时间:2024/05/21 16:36

1.TreeSet介绍

TreeSet集合底层采用红黑树算法,会对存储的元素默认使用自然排序(从小到大).
注意: 必须保证TreeSet集合中的元素对象是相同的数据类型,否则报错.


2.TreeSet的排序规则

自然排序(从小到大):
TreeSet调用集合元素的compareTo方法来比较元素的大小关系,然后将集合元素按照升序排列(从小到大).
注意:要求TreeSet集合中元素得实现java.util.Comparable接口.

各种数据类型自然排序规则


java.util.Comparable接口:可比较的.
覆盖 public int compareTo(Object o)方法,在该方法中编写比较规则.
在该方法中,比较当前对象(this)和参数对象o做比较(严格上说比较的是对象中的数据,比如按照对象的年龄排序).
       this  >  o: 返回正整数.  1
       this <   o: 返回负整数.  -1
       this == o: 返回0.     此时认为两个对象为同一个对象.
--------------------------------------
在TreeSet的自然排序中,认为如果两个对象做比较的compareTo方法返回的是0,则认为是同一个对象.


从上图可知,基本上很多类都实现了这个接口,我们来看一下String类源码,可以看出String已经实现Comparable,并覆盖compareTo方法



举例:

import java.util.Set;import java.util.TreeSet;public class SetDemo4 {public static void main(String[] args) {Set<String> set = new TreeSet<>();set.add("a");set.add("A");set.add("abc");set.add("B");System.out.println(set);//打印结果,已经排好序了[A, B, a, abc],按照字符串的Unicode值排序}}
在这里我们如果要想自己定义的类在TreeSet中也能实现自然排序,那么就要根据上面的步骤来实现:

举个例子:首先定义一个Student类,这个类要实现Comparable接口,然后覆盖CompareTo方法,自定义自己需要排序的规则,比如我们这里按照学生的姓名的长度进行自然排序:

class Student implements Comparable<Student>{private int id;private String name;public Student(int id, String name) {super();this.id = id;this.name = name;}public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic String toString() {return "Student [id=" + id + ", name=" + name + "]";}/** * 覆盖compareTo方法 * 根据学生的姓名长度排序 */public int compareTo(Student stu) {if (this.getName().length()>stu.getName().length()) {return 1; }else if (this.getName().length()<stu.getName().length()) {return -1;}else {return 0; //长度相同}}}
测试:打印结果,姓名长度由短到长来排序的

import java.util.Set;import java.util.TreeSet;public class SetDemo4 {public static void main(String[] args) {Set<Student> set = new TreeSet<>();set.add(new Student(1, "聂小倩"));set.add(new Student(1, "西门吹雪"));set.add(new Student(1, "哥"));set.add(new Student(1, "孙斌"));System.out.println(set);//打印结果看下面,说明是按照名字长度从小到大的自然顺序来排序的//[Student [id=1, name=哥], Student [id=1, name=孙斌], Student [id=1, name=聂小倩], Student [id=1, name=西门吹雪]]}}


定制排序(比如从大到小,按照名字的长短来排序):
TreeSet构造器中传递java.lang.Comparator对象.覆盖public int compare(Object o1, Object o2)再编写比较规则.

在TreeSet构造函数中,有一个构造函数可以传入一个比较器对象,他是一个接口,我们需要提供实现类,并覆盖compare方法再编写比较规则.


同样的,我们举个例子,也是按照学生姓名长度排序:

首先也是定义一个学生类:

class Student{private int id;private String name;public Student(int id, String name) {super();this.id = id;this.name = name;}public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic String toString() {return "Student [id=" + id + ", name=" + name + "]";}}
然后定义比较器类:

import java.util.Comparator;//比较器类class NameLengthComparator implements Comparator<Student> {/** * 覆盖compare方法 * 比较规则:同样是根据学生的姓名长度排序 */public int compare(Student s1, Student s2) {if (s1.getName().length() > s2.getName().length()) {return 1;} else if (s1.getName().length() < s2.getName().length()) {return -1;} else {return 0;}}}
测试:

import java.util.Set;import java.util.TreeSet;public class SetDemo5 {public static void main(String[] args) {//创建set对象的时候要传入比较器类对象Set<Student> set = new TreeSet<>(new NameLengthComparator());set.add(new Student(1, "聂小倩"));set.add(new Student(1, "西门吹雪"));set.add(new Student(1, "哥"));set.add(new Student(1, "孙斌"));System.out.println(set);}}
打印结果:

[Student2 [id=1, name=哥], Student2 [id=1, name=孙斌], Student2 [id=1, name=聂小倩], Student2 [id=1, name=西门吹雪]]

既然是定制排序,你可以修改排序规则,按照从长到短来排序,只需要修改比较器类的实现规则

import java.util.Comparator;//比较器类class NameLengthComparator implements Comparator<Student> {/** * 覆盖compare方法 * 比较规则:同样是根据学生的姓名长度排序 */public int compare(Student s1, Student s2) {if (s1.getName().length() < s2.getName().length()) {return 1;} else if (s1.getName().length() > s2.getName().length()) {return -1;} else {return 0;}}}
将if中的>和<修改一下就行了

对于TreeSet集合来说,要么使用自然排序,要么使用定制排序.
判断两个对象是否相等的规则:
自然排序:   compareTo方法返回0;
定制排序:  compare方法返回0;


原创粉丝点击