TreeMap
1.TreeSet
TreeSet底层实际上是一个TreeMap;
TreeMap底层是一个二叉树;
放到TreeSet集合中的元素,等同于放到TreeMap集合的key部分;
TreeSet集合中的元素,无序不可重复,但是可以按照元素的大小顺序自动排序,称为可排序集合;
2.重写Comparable
对于自定义的类型,需要实现Comparable接口并重写CompareTo()方法
(1)未实现Comparable接口
1 package SetTest; 2 3 import java.util.Set; 4 import java.util.TreeSet; 5 6 /* 7 1.TreeSet底层实际上是一个TreeMap; 8 2.TreeMap底层是一个二叉树; 9 3.放到TreeSet集合中的元素,等同于放到TreeMap集合的key部分; 10 4.TreeSet集合中的元素,无序不可重复,但是可以按照元素的大小顺序自动排序,称为可排序集合; 11 12 */ 13 public class TreeSetTest02 { 14 public static void main(String[] args){ 15 TreeSet<Person> ts=new TreeSet<Person>(); 16 Person p1=new Person(1,"张三"); 17 Person p2=new Person(2,"王五"); 18 Person p3=new Person(2,"刘七"); 19 20 ts.add(p1); 21 ts.add(p2); 22 ts.add(p3); 23 24 for(Person pe:ts){ 25 System.out.println(pe.toString()); 26 } 27 28 } 29 30 } 31 32 class Person{ 33 String name; 34 int no; 35 36 public Person(){ 37 38 } 39 public Person(int no,String name){ 40 this.name=name; 41 this.no=no; 42 } 43 @Override 44 public String toString() { 45 return "编号" + no+ ",姓名" + name; 46 } 47 48 49 }

(2)实现Comparable接口并重写CompareTo方法
重写compareTo方法,定义自己设定的比较逻辑:拿着参数k和集合中的每一个k进行比较,返回值可能是:>0、<0、=0
若返回0:value值覆盖;
若返回>0:会继续在右子树上找;
若返回<0:会继续在左子树上找;
1 package SetTest; 2 3 import java.util.Set; 4 import java.util.TreeSet; 5 6 /* 7 1.TreeSet底层实际上是一个TreeMap; 8 2.TreeMap底层是一个二叉树; 9 3.放到TreeSet集合中的元素,等同于放到TreeMap集合的key部分; 10 4.TreeSet集合中的元素,无序不可重复,但是可以按照元素的大小顺序自动排序,称为可排序集合; 11 12 */ 13 public class TreeSetTest02 { 14 public static void main(String[] args){ 15 TreeSet<Person> ts=new TreeSet<Person>(); 16 Person p1=new Person(1,"张三"); 17 Person p2=new Person(2,"王五"); 18 Person p3=new Person(3,"刘七"); 19 20 ts.add(p1); 21 ts.add(p2); 22 ts.add(p3); 23 24 for(Person pe:ts){ 25 System.out.println(pe.toString()); 26 } 27 28 } 29 30 } 31 32 class Person implements Comparable<Person>{ 33 String name; 34 int no; 35 36 public Person(){ 37 38 } 39 public Person(int no,String name){ 40 this.name=name; 41 this.no=no; 42 } 43 @Override 44 public String toString() { 45 return "编号" + no+ ",姓名" + name; 46 } 47 48 //重写compareTo方法,定义自己设定的比较逻辑:拿着参数k和集合中的每一个k进行比较,返回值可能是:>0、<0、=0 49 @Override 50 public int compareTo(Person p) { 51 return this.no-p.no; 52 } 53 54 55 }
运行结果:
编号1,姓名张三
编号2,姓名王五
编号3,姓名刘七
例2:
1 package SetTest; 2 3 import java.util.Set; 4 import java.util.TreeSet; 5 6 7 /* 8 1.TreeSet底层实际上是一个TreeMap; 9 2.TreeMap底层是一个二叉树; 10 3.放到TreeSet集合中的元素,等同于放到TreeMap集合的key部分; 11 4.TreeSet集合中的元素,无序不可重复,但是可以按照元素的大小顺序自动排序,称为可排序集合; 12 13 */ 14 public class TreeSetTest02 { 15 public static void main(String[] args){ 16 17 18 TreeSet<Student> st=new TreeSet<Student>(); 19 20 Student s1=new Student(10,"Tom"); 21 Student s2=new Student(9,"Jack"); 22 Student s3=new Student(9,"Tony"); 23 Student s4=new Student(18,"Tom"); 24 Student s5=new Student(16,"Tim"); 25 st.add(s1); 26 st.add(s2); 27 st.add(s3); 28 st.add(s4); 29 st.add(s5); 30 31 for(Student s:st){ 32 System.out.println(s.toString()); 33 } 34 } 35 36 37 } 38 39 40 class Student implements Comparable<Student>{ 41 42 String name; 43 int age; 44 public Student(int age,String name){ 45 this.age=age; 46 this.name=name; 47 } 48 @Override 49 public String toString() { 50 return "年龄" + age + ", 姓名" + name ; 51 } 52 53 //重写CompareTo方法,按照年龄升序,如果年龄相同,比较名字 54 @Override 55 public int compareTo(Student s) { 56 if(this.age==s.age){ 57 return this.name.compareTo(s.name); 58 }else 59 return this.age-s.age; 60 } 61 62 63 64 } 65 66
运行:

3.自平衡二叉树

4.TreeSet集合钟中元素可排序的第二种方式:使用比较器的方式
单独编写比较器,比较器实现java.util.Comparator接口(Comparable是java.lang包下的,Comparator是java.util包下的)
1 package SetTest; 2 3 import java.util.Comparator; 4 import java.util.TreeSet; 5 6 public class TreeSetTest03 { 7 8 public static void main(String[] args){ 9 10 //创建TreeSet集合的时候,需要使用这个比较器 11 12 //TreeSet<Animal>a=new TreeSet<Animal>();//这样不行,没有通过构造方法传递一个比较器进去 13 14 TreeSet<Animal>a=new TreeSet<Animal>(new AnimalComparator());//给构造方法传递一个比较器进去 15 16 a.add(new Animal(500)); 17 a.add(new Animal(600)); 18 a.add(new Animal(100)); 19 20 for(Animal aa:a){ 21 System.out.println(aa.toString()); 22 } 23 24 25 26 } 27 28 29 } 30 31 class Animal { 32 int age; 33 public Animal(int age){ 34 this.age=age; 35 } 36 @Override 37 public String toString() { 38 return "Animal " + age ; 39 } 40 41 42 43 } 44 //单独编写比较器,比较器实现java.util.Comparator接口(Comparable是java.lang包下的,Comparator是java.util包下的) 45 class AnimalComparator implements Comparator<Animal>{ 46 47 @Override 48 public int compare(Animal o1, Animal o2) { 49 50 return o1.age-o2.age; 51 } 52 53 }
运行结果:
Animal 100
Animal 500
Animal 600
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
使用匿名内部类的方式:
Comparator是个接口,这里不用创建一个类去实现这个接口,而是使用匿名内部类的方式
1 package SetTest; 2 3 import java.util.Comparator; 4 import java.util.TreeSet; 5 6 public class TreeSetTest03 { 7 8 public static void main(String[] args){ 9 10 //创建TreeSet集合的时候,需要使用这个比较器 11 12 13 //使用匿名内部类的方式,Comparator是个接口,不用创建一个类去实现这个接口,而是使用匿名内部类的方式 14 TreeSet<Animal>a=new TreeSet<Animal>(new Comparator<Animal>(){ 15 @Override 16 public int compare(Animal o1, Animal o2) { 17 return o1.age-o2.age; 18 } 19 });//给构造方法传递一个比较器进去 20 21 a.add(new Animal(500)); 22 a.add(new Animal(600)); 23 a.add(new Animal(100)); 24 25 for(Animal aa:a){ 26 System.out.println(aa.toString()); 27 } 28 29 30 31 } 32 33 34 } 35 36 37 class Animal { 38 int age; 39 public Animal(int age){ 40 this.age=age; 41 } 42 @Override 43 public String toString() { 44 return "Animal " + age ; 45 } 46 47 48 49 }
运行结果:
Animal 100
Animal 500
Animal 600
5.总结
放到TreeSet或者TreeMap集合key部分的元素要想做到排序,有两种方式:
(1)第一种:放在集合中的元素实现java.lang.Comparable接口。(就是在类里面实现Comparable接口,然后重写Comparable接口的comparator()方法)

(2)第二种:在构造TreeSet或者TreeMap集合的时候,给它传一个比较器对象。


两种方式如何选择?
当比较规则不会发生改变的时候,或者说比较规则只有一个的时候,建议实现Comparable接口;
当比较规则有多个,并且需要多个比较规则之间频繁切换,使用Comparator接口

浙公网安备 33010602011771号