由来
我们知道基本数据类型的数据(除boolean类型外)需要比较大小的话,之间使用比较运算符即可,但是引用数据类型是不能直接使用比较运算符来比较大小的。那么,如何解决引用类型比较大小的问题?
java.lang.Comparable接口
Java给所有引用数据类型的大小比较,指定了一个标准接口,就是java.lang.Comparable接口:
package java.lang;
public interface Comparable{
int compareTo(Object obj);
}
那么我们想要使得我们某个类的对象可以比较大小,怎么做呢?步骤:
第一步:哪个类的对象要比较大小,哪个类就实现java.lang.Comparable接口,并重写方法。方法体就是你要如何比较当前对象和指定的另一个对象的大小
第二步:对象比较大小时,通过对象调用compareTo方法,根据方法的返回值决定谁大谁小。
- this对象(调用compareTo方法的对象)大于指定对象(传入compareTo()的参数对象)返回正整数
- this对象(调用compareTo方法的对象)小于指定对象(传入compareTo()的参数对象)返回负整数
- this对象(调用compareTo方法的对象)等于指定对象(传入compareTo()的参数对象)返回零
代码示例
定义要比较的引用类型,实现Comparable接口
package sgg1.demo01;
public class Student implements Comparable {
private int id;
private String name;
private int score;
//全参构造
public Student(int id, String name, int score) {
this.id = id;
this.name = name;
this.score = score;
}
// 无参构造
public Student() {
}
@Override
public String toString() { //toString等方法
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
", score=" + score +
'}';
}
@Override
public int compareTo(Object o) {
//这些需要强制,将o对象向下转型为Student类型的变量,才能调用Student类中的属性
Student stu = (Student) o;
if (this.score != stu.score) {//先按照成绩排序
return this.score - stu.score;
} else {//成绩相同,按照学号比较大小
return this.id - stu.id;
}
}
//get/set、等方法
}
自定义数组排序工具类
package sgg1.utils;
public class SortArray {
// 排序的方法都实现了Comparable接口,因此可以使用 Comparable[] arr 作为参数
public static void sort(Comparable[] arr) {
//冒泡排序
for (int i = 0; i < arr.length - 1; i++) {
for (int j = 0; j < arr.length - i - 1; j++) {
//将arr[j]强制为Comparable接口类型,目的是调用compareTo方法
//当然如果数组的元素没有实现这个接口,那么将会发生ClassCastException
if (arr[j].compareTo(arr[j + 1]) > 0) {
Comparable temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}
}
定义测试类
import sgg1.utils.SortArray;
import java.util.Arrays;
public class Test {
public static void main(String[] args) {
Student s1 = new Student(1,"张三",52);
Student s2 = new Student(2,"李四",5);
Student s3 = new Student(3,"王五",5);
Student s4 = new Student(4,"赵六",555);
Student s5 = new Student(5,"田七",-100);
Student[] students = {s1, s2, s3, s4, s5};
for (int i = 0; i < students.length; i++) {
System.out.println(students[i]);
}
SortArray.sort(students);
System.out.println("==============================");
for (int i = 0; i < students.length; i++) {
System.out.println(students[i]);
}
}
}
执行结果
java.util.Comparator接口
(1)如果一个类,没有实现Comparable接口,而这个类你又不方便修改(例如:一些第三方的类,你只有.class文件,没有源文件),那么这样类的对象也要比较大小怎么办?
(2)如果一个类,实现了Comparable接口,也指定了两个对象的比较大小的规则,但是此时此刻我不想按照它预定义的方法比较大小,但是我又不能随意修改,因为会影响其他地方的使用,怎么办?
JDK在设计类库之初,也考虑到这种情况了,所以又增加了一个java.util.Comparator接口。
package java.util;
public interface Comparator{
int compare(Object o1,Object o2);
}
那么么我们想要比较某个类的两个对象的大小,怎么做呢?步骤:
第一步:编写一个类,我们称之为比较器类型,实现java.util.Comparator接口,并重写方法。方法体就是你要如何指定的两个对象的大小,也就是比较规则。
第二步:比较大小时,通过比较器类型的对象调用compare()方法,将要比较大小的两个对象作为compare方法的实参传入,根据方法的返回值决定谁大谁小。
- o1对象大于o2返回正整数
- o1对象小于o2返回负整数
- o1对象等于o2返回零
代码示例
一个没有实现Comparable接口的学生类
public class Student {
public int id;
public String name;
public int age;
public double score;
//全参构造
public Student(int id, String name,int age, double score) {
this.id = id;
this.name = name;
this.age=age;
this.score = score;
}
// 无参构造
public Student() {
}
//省略了get和set、等方法
@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
", score=" + score +
'}';
}
}
定义定制比较器类
import java.util.Comparator;
//比较器类型,实现java.util.Comparator接口,并重写方法
public class ComparatorSort implements Comparator {
@Override
public int compare(Object o1, Object o2) {
Student s1 = (Student) o1;
Student s2 = (Student) o2;
//如果年龄相等就比较score
if (s1.age == s2.age) {
return Double.compare(s1.score, s2.score);
}
//根据年龄比较
return s1.age - s2.age;
}
}
自定义数组工具类,给任意对象数组用冒泡排序实现从小到大排序,
public class SortArray {
//
public static void comparatorSort(Object[] objects, Comparator comparator){
//冒泡排序
for (int i = 0; i < objects.length-1; i++) {
for (int j = 0; j < objects.length-1-i; j++) {
//通过比较器类型的对象调用compare()方法,将要比较大小的两个对象作为compare方法的实参传入,
// 根据方法的返回值决定谁大谁小。
if (comparator.compare(objects[j],objects[j+1]) > 0){
Object temp = objects[j];
objects[j] = objects[j+1];
objects[j+1] = temp;
}
}
}
}
}
测试代码
import sgg1.utils.ComparatorSort;
import sgg1.utils.SortArray;
import java.util.Arrays;
import java.util.Comparator;
public class Test {
public static void main(String[] args) {
Student s1 = new Student(1, "张三1", 18, 1.2);
Student s2 = new Student(2, "张三2", 2, 321.2);
Student s3 = new Student(3, "张三3", 48, 4.2);
Student s4 = new Student(4, "张三4", 448, 2.2);
Student s5 = new Student(5, "张三5", 48, 62.2);
Student s6 = new Student(6, "张三6", 38, 5.2);
Student[] students = {s1, s2, s3, s4, s5, s6};
for (Student student : students) {
System.out.println(student);
}
//创建比较器对象
ComparatorSort cs = new ComparatorSort();
//调用自定义工具类的方法
SortArray.comparatorSort(students, cs);
System.out.println("===================");
for (Student student : students) {
System.out.println(student);
}
}
}
执行结果