从Java中TreeMap集合来引出外部比较器和内部比较器的一些用法

从Java中TreeMap集合来引出外部比较器和内部比较器的一些用法

引出:从TreeMap的put方法中来看
在这里插入图片描述
在往TreeMao集合里添加元素的时候,会进行比较添加元素的key值,这时就会用到比较器,在源码中有两种比较器。
在这里插入图片描述

将元素的key值进行比较,调用key值自己的compareTo 这有两种情况:

[1] key值自己是系统定义好的,像Integer、String等,那么Integer或String本身自带compareTo方法,然后来进行比较

  • 从代码中看
public class Test01 {
    public static void main(String[] args) {
        //这里的key是String它自身带了比较器即比较的方法,因此不需要自己来弄比较器
        TreeMap<String, Integer> treeMap = new TreeMap<>();
        treeMap.put("Tom",101);
        treeMap.put("Confidence",101);
        treeMap.put("Excellent",101);
        treeMap.put("Apple",101);
        treeMap.put("Google",101);
        System.out.println(treeMap);
    }
}
/*运行结果:
*{Apple=101, Confidence=101, Excellent=101, Google=101, Tom=101}
*Process finished with exit code 0

[2] key值是自己重新定义的一个类,那么这个类一开始是没有compareTo方法的,那么它就得自己弄一个compareTo方法。
方法:自己定义的key值类先实现一个接口,分为两种情况
(1)自定义类实现Comparable<key的自定义类>接口,这种被称为内部比较器,在创建TreeMap集合对象时不用往参数里添加比较的那个对象。

  • 从代码中看:
public class Student implements Comparable<Student>{
    private int Std;
    private String name;
//这个类其他方法先省略,只看实现Comparable接口的compareTo方法
    //如这个方法所示,比较了Student类的对象的std属性,参数是Student对象,最后用int返回
    @Override
    public int compareTo(Student o) {
        return this.getStd()-o.getStd();
    }
}
import java.util.TreeMap;
public class Test01 {
    public static void main(String[] args) {
    //这里由于是Student类自己内部定义好了比较的方法,因此构造器这里不用传参数即比较器对象。
        TreeMap<Student, Integer> map = new TreeMap<>();
        map.put((new Student(105,"Tom")),103);
        map.put((new Student(103,"Tqm")),103);
        map.put((new Student(102,"Trm")),104);
        map.put((new Student(108,"Txm")),106);
        System.out.println(map);
    }
}
/*运行结果:
*{Student{Std=102, name='Trm'}=104, Student{Std=103, name='Tqm'}=103, Student{Std=105, name='Tom'}=103, Student{Std=108, name='Txm'}=106}
*Process finished with exit code 0
* */

(2)自定义类实现Comparator<key的自定义类>接口,这种被称为外部比较器,在创建TreeMap集合对象时需要往参数里添加比较器的对象

  • 从代码来看
  • 方法一:
public class Student {
//为了节约空间,这个类在这里只显示了它的属性
    private int Std;
    private String name;
}
//自己定义一个比较类名字为CompareName
class CompareName implements Comparator<Student>{
    //这个类实现了Comparator接口,它是一个外部比较器的接口,
    //如下面方法所示,这个compare方法用来比较传进参数的两个Student对象的name属性
    @Override
    public int compare(Student o1, Student o2) {
        return o1.getName().compareTo(o2.getName());
    }
}
public class Test01 {
    public static void main(String[] args) {
        //创建比较类的对象
        CompareName cn = new CompareName();
        //在创建对象时,传入比较类的对象,因为到时候要调用这个比较类对象里的比较方法
        TreeMap<Student, Integer> map = new TreeMap<>(cn);
        map.put((new Student(105,"Tom")),103);
        map.put((new Student(103,"Cat")),103);
        map.put((new Student(102,"Excellent")),104);
        map.put((new Student(108,"Legend")),106);
        map.put((new Student(108,"Apple")),106);
        System.out.println(map);
    }
}
/*运行结果:
 * {Student{Std=108, name='Apple'}=106, Student{Std=103, name='Cat'}=103, 
 * Student{Std=102, name='Excellent'}=104, Student{Std=108, name='Legend'}=106, 
 * Student{Std=105, name='Tom'}=103}
 * Process finished with exit code 0
 * */
  • 可能会有个疑问,为啥在创建TreeMap集合对象时可以传进自己定义那个类的对象呢?
    下面我们从源码来看:
    在这里插入图片描述
    在这里插入图片描述
  • 方法二:其实跟方法一差不多 只不过是在定义 比较类的时候直接在创建TreeMap集合对象那里进行操作,如下面代码所示:
public class Student {
//为了节约空间,这个类在这里只显示了它的属性
    private int Std;
    private String name;
}
import java.util.Comparator;
import java.util.TreeMap;

public class Test01 {
    public static void main(String[] args) {
    /*既然这里构造器的参数为一个Comparator接口声明的一个自己定义比较类的对象
    * 那么这里直接new一个岂不是更方便,虽然操作有点诡异,但是可以节约内存,每次指向完后
    * 直接释放掉内存,这里即用到了匿名内部类的操作,这里直接重写Comparator接口下的compare方法
    * 参数是两个Student对象,返回一个int类型的数值,这里重写的方法是比较两个Student对象的name属性*/
        TreeMap<Student, Integer> map = new TreeMap<>(new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                return o1.getName().compareTo(o2.getName());
            }
        });
        map.put((new Student(105,"Tom")),103);
        map.put((new Student(103,"Cat")),103);
        map.put((new Student(102,"Excellent")),104);
        map.put((new Student(108,"Legend")),106);
        map.put((new Student(108,"Apple")),106);
        System.out.println(map);
    }
}
/*运行结果:
* {Student{Std=108, name='Apple'}=106, Student{Std=103, name='Cat'}=103,
* Student{Std=102, name='Excellent'}=104, Student{Std=108, name='Legend'}=106,
* Student{Std=105, name='Tom'}=103}
* Process finished with exit code 0
* */

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值