对象的比较

简介: 对象的比较

1. equals( ) 方法



举个例子,我们现在创建一个类 Card 表示一张扑克牌的信息,在主函数中,我们创建三个对象,也就是三张扑克牌,那么我们现在尝试着比较一下这两张牌。我们认为:只有当两张的牌的数值和花色都相同的时候,才觉得这两张牌是相同的。


我们利用 IDEA 编译器自动生成一个重写的equals( ) 方法


总结一下 equals( ) 方法:


① 如果指向同一个对象,返回 true

② 如果传入的为 null,返回 false

③ 如果比较的两个对象,一个是 Card 类,一个是 People 类,返回 false,这很好理解,你不能拿一张牌和一个人去比较!

④ 按照类的实现目标完成比较,例如这里只有扑克牌的花色和数值一样,我们才认为是相同的牌,逻辑问题可以自己实现。

⑤ equals( ) 方法主要可以用来比较自定义的引用类型,但equals( ) 方法缺陷是:其只能按照相等进行比较,不能按照大于、小于的方式进行比较。也就是说,使用equals( ) 方法后的输出结果,只有 true 和 false 之分。


class Card {
    public int rank;    // 数值
    public String suit; // 花色
    public Card(int rank, String suit) {
        this.rank = rank;
        this.suit = suit;
    }
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Card card = (Card) o;
        return rank == card.rank && Objects.equals(suit, card.suit);
        //只有当两个对象的 数值和花色 相同的时候,才会返回 true
    }
    @Override
    public int hashCode() {
        return Objects.hash(rank, suit);
    }
}
public class Test {
    public static void main(String[] args) {
        Card card1 = new Card(1,"♥");
        Card card2 = new Card(2,"♠");
        Card card3 = new Card(1,"♥");
        System.out.println(card1.equals(card2));
        System.out.println(card1.equals(card3));
    }
}


输出结果:


e242ed431fa14de69665acd34d0cfcf8.png


2. Comparable 接口



[ Comparable 接口、Comparator 接口 ] 这两个接口和我之前写的C语言博客qsort函数十分相似,思想是一样的,感兴趣的读者可以去翻一翻我的博客,这是链接:


qsort函数


引入:假设我们现在手中有一张学生名单,上面有他们的各种信息,那么我们想什么办法给这些学生进行排序呢?我们可以按名字首字母排序,也可以按年龄排序,当然在初中高中,每次月考完,都是按成绩排序。所以在程序清单1中,我们创建一个类 Student,表示一个学生,类中有其名字、年龄、成绩。此时我们生成一个带三个参数的构造方法。我们先让类实现接口 Comparable,在类 Student 中,我们重写方法 compareTo.


在主函数中,我们创建两个对象,然后通过对象变量 student1 调用这个 compareTo方法,进行比较 student2,我们先来将学生按名字进行排序吧!那么在 compareTo 中,this.age 就等价于 student1.age,o.age 就等价于 student2.age,也就是说:我们拿学生1和学生2的年龄进行排序,而实现这一功能,就需要使用 Comparable 接口。如果学生1的年龄大于学生2,那么就返回正数,反之,返回负数。


在程序清单1中,我们发现,类 Student 实现了 Comparable 接口,那么在类中必须重写 Comparable 接口的方法 compareTo( ). 当然,Comparable 接口就是为了比较而设计的,而其对应的 compareTo( ) 方法也是如此。


程序清单1:


class Student implements Comparable<Student>{
    public String name;
    public int age;
    public double score;
    public Student(String name, int age, double score) {
        this.name = name;
        this.age = age;
        this.score = score;
    }
    @Override
    public int compareTo(Student o) {
        return this.age - o.age;
    }
}
public class Test {
    public static void main(String[] args) {
        Student student1 = new Student("A",21,90);
        Student student2 = new Student("C",28,75);
        System.out.println(student1.compareTo(student2));
    }
}


输出结果:


d12e1c63763e4ba6bd9fa385d11b9ee9.png


在程序清单2中,我们选择让学生以年龄升序:


使用Arrays.sort() 方法的时候,编译器不知道我们是基于什么方式进行排序的,
因为 students 数组中,有三个不同的类型。
那么我们就实现比较接口,告诉编译器,以学生名字进行怕排序。


程序清单2:


class Student implements Comparable<Student>{
    public String name;
    public int age;
    public double score;
    public Student(String name, int age, double score) {
        this.name = name;
        this.age = age;
        this.score = score;
    }
    @Override
    public int compareTo(Student o) {
        return this.age - o.age;
    }
    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", score=" + score +
                '}';
    }
}
public class Test {
    public static void main(String[] args) {
        Student[] students = new Student[3];
        students[0] = new Student("A",21,90);
        students[1] = new Student("C",28,75);
        students[2] = new Student("B",24,70);
        System.out.println(Arrays.toString(students));
        Arrays.sort(students);
        System.out.println(Arrays.toString(students));
    }
}


输出结果:


de21eeb7fe75415a8c9f808f5971e942.png


如果我们让学生以名字降序,那么我们就改变 compareTo 方法中的代码,代码如下:【 o.age - this.age 】


public int compareTo(Student o) {
  return o.age - this.age;
}


同样地,如果我们让学生以成绩升序,那么代码如下:


public int compareTo(Student o) {
  return (int)(this.score - o.score);
}


如果我们让学生以名字升序,那么代码如下:


public int compareTo(Student o) {
  return this.name.compareTo(o.name);
}


读者可以自己去试一下这些操作,了解不同类型的比较方式。


3. Comparator 接口



我们来看一下 Comparator 接口来排序两个学生年龄的大小,与 Comparable 接口的思想相同,接下来我主要说明一下 Comparator 接口的语法。


在程序清单3中,我们需要额外创建一个类 AgeComparator 来实现 Comparator 接口,并在这个类中,我们创建一个重写方法 compare( ),那么在主函数中,我们传参只需要传两个对象变量 student1 和 student2 就可以了,那么回过头来看方法 compare( ),student1.age 就等价于 o1.age;student2.age 就等价于 o2.age.


与上面的 Comparable 接口思想相同,不管哪个类实现了接口,那么一定要重写对应接口中的抽象方法。接下来,让我们看一下 Comparator 接口是怎么进行实现的吧。


程序清单3:


class Student {
    public String name;
    public int age;
    public double score;
    public Student(String name, int age, double score) {
        this.name = name;
        this.age = age;
        this.score = score;
    }
}
class AgeComparator implements Comparator<Student> {
    @Override
    public int compare(Student o1, Student o2) {
        return o1.age - o2.age;
    }
}
public class Test {
    public static void main(String[] args) {
        Student student1 = new Student("Z",11,85);
        Student student2 = new Student("Y",18,73);
        AgeComparator ageComparator = new AgeComparator();
        System.out.println(ageComparator.compare(student1, student2));
    }
}


输出结果:


4d4b62e477074bbbb8fbdd4f7db48552.png


在程序清单4中,我将一个学生的三个参数分别进行了排列。


程序清单4:


class Student {
    public String name;
    public int age;
    public double score;
    public Student(String name, int age, double score) {
        this.name = name;
        this.age = age;
        this.score = score;
    }
    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", score=" + score +
                '}';
    }
}
//年龄排序
class AgeComparator implements Comparator<Student> {
    @Override
    public int compare(Student o1, Student o2) {
        return o1.age - o2.age;
    }
}
//成绩排序
class ScoreComparator implements Comparator<Student>{
    @Override
    public int compare(Student o1, Student o2) {
        return (int)(o1.score - o2.score);
    }
}
//名字首字母排序
class NameComparator implements Comparator<Student>{
    @Override
    public int compare(Student o1, Student o2) {
        return o1.name.compareTo(o2.name);
    }
}
public class Test {
    public static void main(String[] args) {
        Student[] students = new Student[3];
        students[0] = new Student("Z",11,85);
        students[1] = new Student("Y",18,73);
        students[2] = new Student("X",14,80);
        System.out.println(Arrays.toString(students));
        System.out.println();
        AgeComparator ageComparator = new AgeComparator();
        Arrays.sort(students, ageComparator);
        System.out.println(Arrays.toString(students));
        System.out.println();
        ScoreComparator scoreComparator = new ScoreComparator();
        Arrays.sort(students,scoreComparator);
        System.out.println(Arrays.toString(students));
        System.out.println();
        NameComparator nameComparator= new NameComparator();
        Arrays.sort(students,nameComparator);
        System.out.println(Arrays.toString(students));
        System.out.println();
    }
}


输出结果:


a897007ccc45402d9a18a30b37be5a86.png


可以发现 Comparator接口更加“定制化”,需要什么类型的排序,我就额外创建一个类来实现此接口,之后再通过主函数(或其他方法)调用即可。

目录
相关文章
|
6月前
|
C++
C++中的对象
C++中的对象
54 2
|
6月前
|
测试技术 索引
v-for 与对象
v-for 与对象
|
前端开发
67 # 对象的处理
67 # 对象的处理
34 0
|
存储 程序员 编译器
C++都有对象了,你还没有吗?
C++都有对象了,你还没有吗?
83 0
|
Java 开发者 容器
你有对象吗?
你有对象吗?
107 0
|
存储 JSON Java
谈“对象“
谈“对象“
|
存储 编译器 C语言
我现在必须new一个对象!!!
C++内存管理,手动开辟空间,我现在必须new一个对象!!!
89 0
我现在必须new一个对象!!!
|
算法 Java
对象的比较
本篇文章是对Java中一些常见的比较的总结,在涉及到比较方面,有元素的比较与对象的比较,下边博主来带领大家一起了解这些比较方式。
109 0