Java中经常会涉及到对象数组的排序问题,那么就涉及到对象之间的比较问题。
通常对象之间的比较可以从两个方面去看:
第一个方面:对象的地址是否一样,是否引用自同一个对象。这种方式可以直接使用“==“来完成。
第二个方面:以对象的某一个属性的角度去比较,例如以对象的年龄、出生年月、成绩分数、姓氏字母等。
从最新的JDK8而言,有三种实现对象比较的方法:
一、覆写Object类的equals()方法,即直接写在类里面;
二、继承Comparable接口,并实现compareTo()方法;
三、定义一个单独的对象比较器,继承自Comparator接口,实现compare()方法。
由于使用的排序方式的不同,具体选择哪种方法来实现对象的比较也会有所不同。
方式1: 覆写equals()方法
覆写equals()方法,一般用于自己实现对象数组排序的情况,而对于要使用java内置的排序算法时,使用后面两种方式都是可行的。
方式2: 继承Comparable接口,并实现 compareTo()方法
这种方式就是让自己编写的类继承Comparable接口,并实现compareTo()方法,这种情况下,在使用java.util.Arrays.sort() 方法时,不用指定具体的比较器,sort()方法会使用对象自己的比较函数来完成对象的排序。
方式3:继承自Comparator接口,实现compare()方法
一般使用以上两种方法就能够满足实际的开发问题,但是当出现以下情况时,就需要用到Comparator接口:要在已经开发好的代码的基础上完善对象的比较功能时,又不想更改之前的代码,这种情况下,从JDK1.8之后出现了Comparator接口,是对这种情况的一个弥补。
这种情况下,需要单独定义一个对象比较器,继承Comparator接口,并实现compare()方法。
以上三种实现方式的示例代码如下:
package com.mymaven.javademo;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
/**
* @since 2017.03.31
* @author mimvp
*
*/
class Student {
private String name;
private double score;
public Student(String name, double score) {
this.name = name;
this.score = score;
}
public String getName() {
return this.name;
}
public double getScore() {
return this.score;
}
@Override
public String toString(){
return "Student:name: " + this.name + "; score: " + this.score;
}
// 方式1: 覆写equals()方法
public int equals(Student s) {
int result = this.score > s.getScore() ? 1 : (this.score < s.getScore() ? -1 : 0);
if(0 == result) {
result = this.name.charAt(0) >= s.getName().charAt(0) ? 1 : -1;
}
return result;
}
}
/**
* 方式2: 继承Comparable接口,并实现 compareTo()方法
*/
@SuppressWarnings("rawtypes")
class Teacher implements Comparable {
private String name;
private double score;
public Teacher(String name, double score) {
this.name = name;
this.score = score;
}
public String getName() {
return this.name;
}
public double getScore() {
return this.score;
}
@Override
public String toString() {
return "Teacher:name: " + this.name + "; score: " + this.score;
}
public int compareTo(Object obj) {
Teacher t = (Teacher) obj;
int result = this.score > t.score ? 1 : (this.score < t.score ? -1 : 0);
if(result == 0) {
result = this.name.indexOf(0) > t.name.indexOf(0) ? 1 : -1;
}
return result;
}
}
/**
* 方式3: 继承自Comparator接口,实现compare()方法
*/
class StudentComparator implements Comparator {
public int compare(Student s1, Student s2) {
int result = s1.getScore() > s2.getScore() ? 1 : (s1.getScore() < s2.getScore() ? -1 : 0);
if(0 == result) {
result = s1.getName().indexOf(0) > s2.getName().indexOf(0) ? 1 : -1;
}
return result;
}
}
/**
* 主函数
*/
public class JavaDemo {
@SuppressWarnings("unchecked")
public static void main(String[] args ) {
System.out.println("hello world");
// 方式1
Student s1 = new Student("zzz", 80);
Student s2 = new Student("bbb", 80);
System.out.println(s1.getName() + " >= " + s2.getName() + " : " + s1.equals(s2));
// 方式2
List teachers = new ArrayList(10);
teachers.add(new Teacher("ddd", 60));
teachers.add(new Teacher("aaa", 60));
teachers.add(new Teacher("bbb", 80));
teachers.add(new Teacher("ccc", 70));
Collections.sort(teachers);
System.out.println(teachers);
// 方式3
Student[] students = new Student[] {
new Student("ddd", 60),
new Student("aaa", 60),
new Student("bbb", 80),
new Student("ccc", 70),
};
Arrays.sort(students, new StudentComparator());
System.out.println(Arrays.deepToString(students));
}
}
运行结果:
hello world
zzz >= bbb : 1
[Teacher:name: aaa; score: 60.0, Teacher:name: ddd; score: 60.0, Teacher:name: ccc; score: 70.0, Teacher:name: bbb; score: 80.0]
[Student:name: aaa; score: 60.0, Student:name: ddd; score: 60.0, Student:name: ccc; score: 70.0, Student:name: bbb; score: 80.0]
1. Comparator 和 Comparable 相同的地方
他们都是java的一个接口, 并且是用来对自定义的class类对象的比较大小,什么是自定义class:
如 public class Person{ String name; int age }
当我们有这么一个personList,里面包含了person1, person2, persion3....., 我们用Collections.sort( personList ), 是得不到预期的结果的. 这时肯定有人要问, 那为什么可以排序一个字符串list呢:
如 StringList{"hello1" , "hello3" , "hello2"}, Collections.sort( stringList ) 能够得到正确的排序, 那是因为
String 这个对象已经帮我们实现了 Comparable接口 , 所以我们的 Person 如果想排序, 也要实现一个比较器。
2. Comparator 和 Comparable 的区别
Comparable
Comparable 定义在 Person类的内部:
public class Persion implements Comparable {..比较Person的大小..}
因为已经实现了比较器,那么我们的Person现在是一个可以比较大小的对象了,它的比较功能和String完全一样,可以随时随地的拿来
比较大小,因为Person现在自身就是有大小之分的。Collections.sort(personList)可以得到正确的结果。
Comparator
Comparator 是定义在Person的外部的, 此时我们的Person类的结构不需要有任何变化,如
public class Person{ String name; int age },
然后我们另外定义一个比较器:
public PersonComparator implements Comparator() {..比较Person的大小..}
在PersonComparator里面实现了怎么比较两个Person的大小. 所以,用这种方法,当我们要对一个 personList进行排序的时候,
我们除了了要传递personList过去, 还需要把PersonComparator传递过去,因为怎么比较Person的大小是在PersonComparator里面实现的, 如:
Collections.sort( personList , new PersonComparator() )
参考推荐: