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接口

posted @ 2021-01-16 14:48  L1998  阅读(584)  评论(0)    收藏  举报