尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

【equals 、Comparable、Comparator 三者的区别】

【equals 、Comparable、Comparator 三者的区别】 作者 小飞学编程…_CSDN博客-编程小白专栏JavaEE初阶标题equals 、Comparable、Comparator 三者的区别equals 、Comparable、Comparator 三者的区别引言equals判断对象是否相等Comparable内部比较器类自己会排序Comparator外部比较器灵活定制排序对比图代码案例1. 基础实体类Student整合 equals Comparable2. 外部比较器Comparator多种排序规则3.测试类运行看效果注意引言1.equals判断两个对象是不是相等 / 同一个2.Comparable让类本身自带「和别人比大小」的能力内部比较器3.Comparator单独做一个裁判工具灵活定制排序规则外部比较器equals判断对象是否相等本质它是 Java 所有类的老祖宗Object类里的方法所有对象天生就有。默认规则用比较比的是两个对象的内存地址—— 也就是判断 “是不是同一个对象”。为什么要重写默认规则不符合业务需求。比如你 new 了两个学生对象学号都是 1001现实里我们认为是同一个学生但默认 equals 会返回false因为是两个不同的对象地址不一样Comparable内部比较器类自己会排序本质1.它是java.lang包下的接口里面只有一个方法int compareTo(T o)。2.一个类实现了 Comparable 接口就代表这个类的对象「天生就可以排序、比大小」。3.排序规则写在类的内部一个类只能有1 种默认排序规则。返回值规则记死这个当前对象 对方 → 返回正数当前对象 对方 → 返回0当前对象 对方 → 返回负数Comparator外部比较器灵活定制排序本质1.它是java.util包下的接口核心方法是int compare(T o1, T o2)。2.它是独立的比较器类不写在原类里面单独写一个类实现 Comparator。3.一个原类可以对应无数种排序规则想怎么比就怎么写比较器。用法排序时把比较器对象传进去对比图代码案例1. 基础实体类Student整合 equals Comparable这个学生类里我们同时做了两件事1.重写 equals() hashCode()自定义「学号相同就算同一个学生」的相等规则2.实现 Comparable 接口给类加上「默认按学号升序排序」的能力importjava.util.Objects;// 实现 ComparableStudent → 类本身自带排序能力内部比较器publicclassStudentimplementsComparableStudent{privateStringid;// 学号privateStringname;// 姓名privateintage;// 年龄// 构造方法创建对象时赋值publicStudent(Stringid,Stringname,intage){this.idid;this.namename;this.ageage;}// getter方法外部读取私有属性publicStringgetId(){returnid;}publicStringgetName(){returnname;}publicintgetAge(){returnage;}// 重写toString打印对象时能看到具体内容而不是内存地址OverridepublicStringtoString(){returnStudent{学号id\, 姓名name\, 年龄age};}// // 第一部分重写 equals() hashCode()// 作用自定义「两个对象什么时候算相等」// Overridepublicbooleanequals(Objecto){// 1. 地址相同 → 肯定是同一个对象直接返回trueif(thiso)returntrue;// 2. 对方为空 / 类型不匹配 → 直接不相等if(onull||getClass()!o.getClass())returnfalse;// 3. 强转类型比较核心属性学号相同就认为相等Studentstudent(Student)o;returnObjects.equals(id,student.id);}// Java强制规范equals相等的对象hashCode必须相等// 用HashMap、HashSet去重时依赖这个不一起重写会出bugOverridepublicinthashCode(){returnObjects.hash(id);}// // 第二部分实现 Comparable 接口的 compareTo 方法// 作用定义类的「默认排序规则」// OverridepublicintcompareTo(Studentother){// 返回值规则必须记牢// 正数 → 当前对象 对方// 0 → 当前对象 对方// 负数 → 当前对象 对方// 这里定义默认按学号从小到大升序// 字符串自带compareTo方法按字典序比较returnthis.id.compareTo(other.id);}}2. 外部比较器Comparator多种排序规则Comparator 是独立于 Student 类之外的「裁判」想加多少种排序规则就写多少个完全不用改 Student 类的代码。2.1按年龄升序的比较器importjava.util.Comparator;// 外部比较器1按年龄 从小到大 排序publicclassAgeAscComparatorimplementsComparatorStudent{Overridepublicintcompare(Students1,Students2){// s1 - s2 → 升序// s2 - s1 → 降序returns1.getAge()-s2.getAge();}}2.2按姓名字典序的比较器importjava.util.Comparator;// 外部比较器2按姓名字典序排序publicclassNameComparatorimplementsComparatorStudent{Overridepublicintcompare(Students1,Students2){returns1.getName().compareTo(s2.getName());}}3.测试类运行看效果importjava.util.ArrayList;importjava.util.Collections;importjava.util.Comparator;importjava.util.List;publicclassTestDemo{publicstaticvoidmain(String[]args){// 准备3个学生故意打乱顺序ListStudentstudentsnewArrayList();students.add(newStudent(1003,张三,20));students.add(newStudent(1001,李四,18));students.add(newStudent(1002,王五,19));// 测试1equals 相等判断 System.out.println( 1. equals 相等判断 );Students1newStudent(1001,李四,18);Students2newStudent(1001,李四,18);System.out.println( 比内存地址(s1s2));// false两个不同对象System.out.println(equals 比学号s1.equals(s2));// true学号相同System.out.println();//测试结果1.equals 相等判断比内存地址falseequals 比学号true// 测试2Comparable 默认排序 System.out.println( 2. Comparable 默认排序按学号升序 );// 不用传额外参数直接用类自带的排序规则Collections.sort(students);for(Students:students){System.out.println(s);}System.out.println();//测试结果2.Comparable默认排序按学号升序Student{学号1001,姓名李四,年龄18}Student{学号1002,姓名王五,年龄19}Student{学号1003,姓名张三,年龄20}// 测试3Comparator 自定义排序 // 方式1用我们单独写好的比较器类System.out.println( 3.1 Comparator 按年龄升序 );Collections.sort(students,newAgeAscComparator());for(Students:students){System.out.println(s);}System.out.println();//测试结果3.1Comparator按年龄升序Student{学号1001,姓名李四,年龄18}Student{学号1002,姓名王五,年龄19}Student{学号1003,姓名张三,年龄20}// 方式2匿名内部类不用单独建类临时写规则System.out.println( 3.2 Comparator 按年龄降序匿名内部类 );Collections.sort(students,newComparatorStudent(){Overridepublicintcompare(Studento1,Studento2){// o2 - o1 → 降序returno2.getAge()-o1.getAge();}});for(Students:students){System.out.println(s);}System.out.println();//测试结果3.2Comparator按年龄降序匿名内部类Student{学号1003,姓名张三,年龄20}Student{学号1002,姓名王五,年龄19}Student{学号1001,姓名李四,年龄18}// 方式3Java 8 Lambda 简写工作中最常用System.out.println( 3.3 Comparator 按姓名排序Lambda写法 );Collections.sort(students,(o1,o2)-o1.getName().compareTo(o2.getName()));// 还可以再简化方法引用// Collections.sort(students, Comparator.comparing(Student::getName));for(Students:students){System.out.println(s);}}}//测试结果3.3Comparator按姓名排序Lambda写法Student{学号1001,姓名李四,年龄18}Student{学号1002,姓名王五,年龄19}Student{学号1003,姓名张三,年龄20}注意Collections.sort(集合,比较器对象);Collections集合工具类java.util包提供集合静态方法①第一个参数 students要排序的List 集合会直接修改原集合排序后集合内元素顺序改变②第二个参数 new AgeAscComparator()创建一个比较器实例告诉 sort 用什么规则比较两个 Student 对象
返回列表