天天看点

Java(3)--Collections排序(Comparable和Comparator接口的实现)前言接口分析程序示例反思总结

文章目录

  • 前言
  • 接口分析
    • Comparable接口
    • Comparator接口
    • compareTo和compare方法
    • 相关之处
  • 程序示例
    • 调用默认的Comparable接口
    • 调用重写compareTo方法的Comparable接口
      • 注意事项
    • 调用重写compareTo方法的Comparator接口
    • 调用重写compareTo方法的Comparator接口实现绝对值排序
  • 反思总结

前言

  • 包装类Collections的排序方法可以运用到各种集合框架,非常方便
  • 分析看不懂请结合程序示例看
  • 有问题欢迎评论或者私信!!!

接口分析

Comparable接口

  • Comparable接口在 java.lang.Comparable 包下
  • Comparable接口的实现方法:public int compareTo(T t);
  • Comparable接口是在集合的(类的)内部实现的排序方式,调用的实质 t1.compareTo(t2);
  • 在排序对象本身支持相互比较所需要的接口(如Integer、String、Double、Float等)时,可以直接调用 Collections.sort() 方法的Comparable接口(参考程序示例)
  • 当数值或ASCII码值从小到大的默认顺序或者排序的根据对象不满足程序需求时,可以重写compareTo方法(参考程序示例)

Comparator接口

  • Comparator接口在 java.util.Comparator 包下
  • Comparator接口的实现方法:public int compare(T t1, T t2);
  • Comparator接口是在集合的(类的)外部实现的排序方式,需要用到一个比较容器,调用的实质是 compare(t1 , t2);(参考程序示例)
  • 在排序对象本身不支持相互比较所需要的接口,例如对整数采用绝对值大小排序,显然对象本身的Integer自然排序是不能实现的,同时如果Integer类也不容许你在它的内部重写compareTo()去改变它的排序行为,所以就可以用到Comparator接口(参考程序示例)

compareTo和compare方法

  • Comparable接口的实现方法:public int compareTo(T t),调用的实质 t1.compareTo(t2);

    在方法内部返回一个运算结果,例如返回:t1.x - t2.x,则按从小到大的顺序排序

    若返回:t2.x - t1.x,则按从大到小的顺序排序

  • Comparator接口的实现方法:public int compare(T t1, T t2),调用的实质是 compare(t1 , t2);

    在方法内部返回一个运算结果,例如返回:t1.x - t2.x,则按从小到大的顺序排序

    若返回:t2.x - t1.x,则按从大到小的顺序排序

  • compareTo默认的调用可以实现字符串的比较,比较方法:先比较第一个字符,不同则返回ASCII码的差值,若第一个字符相同,则比较第二个字符,若前面字符相同则比较长度。

    例如:

    String a = 'abc';
    String b = 'cde';
    String c = 'abcde';
    int d = a.compareTo(b);
    int e = a.compareTo(c);
               

​ 返回d = -2,由a的ASCII码值减去b的ASCII码值得来。e = -2,因为前字符相同,a.length() - c.length() = -2.

相关之处

  • 对于一个对象的排序,既可以用Comparable接口实现,也能用Comparator接口实现,只是两种排序的实现方式不同,
  • 在某些情况的排序下,可以用Comparator接口,在接口的compare方法中再次调用compareTo方法进行比较。例如如下情况:
    输入学生的学号、姓名、班级、成绩,分别根据这四个数据进行排序。

​ 对学号的排序,可以调用Comparable接口重写comparaTo方法按学号从小到大排序

​ 对姓名的排序,可以实现一个比较容器,在容器中重写compare方法,在compare方法中调用compareTo方法实现对字符串的比较,然后返回对字符串的比较结果。

class NameUPComparator implements java.util.Comparator {
    public int compare(Object o1, Object o2) {
        Student s1 = (Student)o1;// 转化成当前类型的对象
        Student s2 = (Student)o2;
        return s1.getName().compareTo(s2.getName());
    }
}
           

在调用sort方法时,则要通过:

程序示例

调用默认的Comparable接口

import java.util.ArrayList;
import java.util.Collections;

public class CompObj {

    public String toString() {
        return "[x = " + x + "]";
    }

    public static void main(String[] args) {
        ArrayList<Integer> al = new ArrayList<Integer>();// 单一Integer数据的ArrayList,有本身支持比较的接口Integer
        al.add(3);
        al.add(1);
        al.add(2);
        System.out.println("Before sort!");
        for (int i = 0; i < al.size(); i++) {
            System.out.println(al.get(i));
        }
        Collections.sort(al); // 调用Collections的sort方法-静态方法
        System.out.println("After sort!");
        for (int i = 0; i < al.size(); i++) {
            System.out.println(al.get(i));
        }
    }
}
           
Java(3)--Collections排序(Comparable和Comparator接口的实现)前言接口分析程序示例反思总结

调用重写compareTo方法的Comparable接口

根据x值排序

import java.util.ArrayList;
import java.util.Collections;

public class CompObj implements java.lang.Comparable { // 定义要排序的类

    int x;
    int y;

    public CompObj(int n1, int n2) {
        x = n1;
        y = n2;
    }

    public String toString() {
        return "[x = " + x + ", y = " + y + "]";
    }

    public int compareTo(Object o) {
        CompObj co = (CompObj) o;
        if (this.x != co.x) {
            return this.x - co.x;
        } else {
            return this.y - co.y;
        }
    }

    public static void main(String[] args) {
        ArrayList<CompObj> al = new ArrayList<CompObj>();
        al.add(new CompObj(3, 1));
        al.add(new CompObj(1, 3));
        al.add(new CompObj(2, 2));
        al.add(new CompObj(2, 1));
        System.out.println("Before sort!");
        for (int i = 0; i < al.size(); i++) {
            System.out.println(al.get(i));
        }
        Collections.sort(al); // 调用Collections的sort方法-静态方法
        System.out.println("After sort!");
        for (int i = 0; i < al.size(); i++) {
            System.out.println(al.get(i));
        }
    }

}
           
Java(3)--Collections排序(Comparable和Comparator接口的实现)前言接口分析程序示例反思总结

注意事项

  • compareTo()方法的形参为Object类的对象,在比较之前要进行类型转换成为CompObj类的对象
  • 在重写的compareTo方法中,若俩对象的x值相同,则比较y值
  • 若改为
    if (this.x != co.x) {
                return co.x - this.x;
            } else {
                return co.y - this.y;
            }
               
    则按照从大到小的顺序排序

调用重写compareTo方法的Comparator接口

根据y值排序

import java.util.ArrayList;
import java.util.Collections;

class ObjComparator implements java.util.Comparator {
    public int compare(Object o1, Object o2) {
        CompObj co1 = (CompObj) o1; // 转化成当前类型的对象
        CompObj co2 = (CompObj) o2;
        if (co1.y != co2.y) {
            return co1.y - co2.y;// 先根据y值排序
        } else {
            return co1.x - co2.x;
        }
    }
}

public class CompObj { // 无需实现Comparable接口
    int x;
    int y;

    public CompObj(int n1, int n2) {
        x = n1;
        y = n2;
    }

    public String toString() {
        return "[x = " + x + ", y = " + y + "]";
    }

    public static void main(String[] args) {
        ArrayList al = new ArrayList();
        al.add(new CompObj(3, 2));
        al.add(new CompObj(1, 3));
        al.add(new CompObj(1, 2));
        System.out.println("Before sort!");
        for (int i = 0; i < al.size(); i++) {
            System.out.println(al.get(i));
        }
        Collections.sort(al, new ObjComparator());
        System.out.println("After sort!");
        for (int i = 0; i < al.size(); i++) {
            System.out.println(al.get(i));
        }
    }
}
           
Java(3)--Collections排序(Comparable和Comparator接口的实现)前言接口分析程序示例反思总结

调用重写compareTo方法的Comparator接口实现绝对值排序

根据x的绝对值排序

import java.util.ArrayList;
import java.util.Collections;

class AbsComparator implements java.util.Comparator {
    public int compare(Object o1, Object o2) {
        CompObj co1 = (CompObj) o1;// 转化成当前类型的对象
        CompObj co2 = (CompObj) o2;
        int v1 = Math.abs(co1.x);// 把对象co1的x成员转化成绝对值
        int v2 = Math.abs(co2.x);
        return v1 - v2;
    }
}

public class CompObj { // 无需实现Comparable接口
    int x;
    int y;

    public CompObj(int n1, int n2) {
        x = n1;
        y = n2;
    }

    public String toString() {
        return "[x = " + x + ", y = " + y + "]";
    }

    public static void main(String[] args) {
        ArrayList al = new ArrayList();
        al.add(new CompObj(3, 2));
        al.add(new CompObj(-2, 3));
        al.add(new CompObj(1, 2));
        System.out.println("Before sort!");
        for (int i = 0; i < al.size(); i++) {
            System.out.println(al.get(i));
        }
        Collections.sort(al, new AbsComparator());
        System.out.println("After sort!");
        for (int i = 0; i < al.size(); i++) {
            System.out.println(al.get(i));
        }
    }
}

           
Java(3)--Collections排序(Comparable和Comparator接口的实现)前言接口分析程序示例反思总结

反思总结

  • 起床整到现在,饿的一批
  • 觉得有帮助到你就点个赞吧🙏🙏🙏
  • 下期出数据结构的约瑟夫问题