目录
- 作用
- 区别
- Comparable使用
- Comparator的使用
- 总结
- 作用
Java的Comparable和Comparator当需要排序的集合或数组不是单纯的数字型时,通常可以使用Comparator或Comparable,以简单的方式实现对象排序或自定义排序。
- 区别
一、Comparable
强行对实现它的每个类的对象进行整体排序,实现此接口的对象列表(和数组)可以通过Collections.sort或Arrays.sort进行自动排序。Comparable是一个内比较器,实现了Comparable接口。是可以和自己比较的。Comparable接口的类的比较,则依赖compareTo方法来实现,compareTo方法也被称为自然比较方法。如果add一个Collection的对象想时想要Collections的sort方自动进行排序的话,那么这个对象必须实现Comparable接口,并重写compareTo方法。compareTo方法有一个参数,返回值是int,有三种情况:
1、新添加进来的对象实例大于已经存在的对象时,返回正整数 1 。表示不同的实例对象,添加至已存在对象的后面。
2、新添加进来的对象实例等于已经存在的对象时,返回 0。表示重复对象实例,则不被添加。
3、新添加进来的对象实例小于已经存在的对象时,返回负整数 -1。表示不同的实例对象,添加至已存在对象的前面。
二、Comparator
强行对某个对象collection进行整体排序的比较函数,可以将Comparator传递给Collections.sort或Arrays.sort。Comparator是一个外比较器,它的比较则是通过重写compare方法来实现的。方法有两个参数T o1和T o2,是泛型的表示方式,分别表示待比较的两个对象,o1表示要添加的新的对象实例,o2表示已经添加进来的对象实例,返回值也是int,分三种情况:
1、o1大于o2,返回正整数 1 。表示不同的实例对象,添加至已存在对象的后面。
2、o1等于o2,返回 0。表示重复对象实例,则不被添加。
3、o1小于o3,返回负整数 -1。表示不同的实例对象,添加至已存在对象的前面。
- Comparable的使用
定义一个类,并实现Comparable接口,重写compareTo方法,根绝返回值编写自己的比较规则。
具体代码实现:
package com.vince;
public class Animal1 implements Comparable<Animal1>{
private String name;
private String color;
private Float weight;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public Float getWeight() {
return weight;
}
public void setWeight(Float weight) {
this.weight = weight;
}
public Animal1(String name, String color, Float weight) {
super();
this.name = name;
this.color = color;
this.weight = weight;
}
@Override
public String toString() {
return "名字:" + name + "\t颜色:" + color + "\t体重:" + weight;
}
//按照体重对动物升序排列
@Override
public int compareTo(Animal1 o) {
// 判断对象是否为空,为空则不添加
if(o == null) {
return 0;
}
if(this.weight >= o.getWeight()) {
return 1;// 对象不为空,如果体重大的则排到后面
}else {
return -1;// 对象不为空,如果体重小的则排到前面
}
}
}
package test;
import java.util.Set;
import java.util.TreeSet;
import com.vince.Animal1;
public class Test2 {
public static void main(String[] args) {
// TODO
Set<Animal1> animals = new TreeSet<>();
animals.add(new Animal1("Monkey", "black", 90f));
animals.add(new Animal1("Duck", "yellow", 5f));
animals.add(new Animal1("Chicken", "white", 7f));
animals.add(new Animal1("Goldfish", "golden", 2f));
animals.add(new Animal1("Elephant", "gray", 250f));
System.out.println("内部比较器升序排序后的结果为:");
for (Animal1 animal : animals) {
System.out.println(animal);
}
}
}
- Comparator
匿名的方式实现Comparator:在创建一个类时,不直接在类当中去实现,而是在测试类中采用匿名内部类的方式,直接创建一个Comparator来实现comparable方法。
具体代码实现:
package com.vince;
public class Animal2 {
private String name;
private String color;
private Float weight;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public Float getWeight() {
return weight;
}
public void setWeight(Float weight) {
this.weight = weight;
}
public Animal2(String name, String color, Float weight) {
super();
this.name = name;
this.color = color;
this.weight = weight;
}
@Override
public String toString() {
return "名字:" + name + "\t颜色:" + color + "\t体重:" + weight;
}
}
package test;
import java.util.Comparator;
import java.util.Set;
import java.util.TreeSet;
import com.vince.Animal2;
public class Test3 {
public static void main(String[] args) {
// 匿名内部类的方式实现比较器降序排序
Set<Animal2> animal2s = new TreeSet<Animal2>(new Comparator<Animal2>() {
@Override
public int compare(Animal2 o1, Animal2 o2) {
// 如果对象都为空则不添加
if(o1 == null || o2 == null) {
return 0;
}
if(o1.getWeight() >= o2.getWeight()) {
return -1;//体重大的放前面
}else {
return 1;//体重小的放前面
}
}
});
animal2s.add(new Animal2("Monkey", "black", 90f));
animal2s.add(new Animal2("Duck", "yellow", 5f));
animal2s.add(new Animal2("Chicken", "white", 7f));
animal2s.add(new Animal2("Goldfish", "golden", 2f));
animal2s.add(new Animal2("Elephant", "gray", 250f));
System.out.println("外部比较器降序排列后的结果为:");
for (Animal2 animal : animal2s) {
System.out.println(animal);
}
}
}
自定义比较器Comparator:另外创建一个比较器类直接在类里面实现compare方法,在测试类直接new一个Comparator。
具体代码实现:
package com.vince;
public class Student {
private Integer classNumber;
private String name;
private char sex;
private Integer age;
public Integer getClassNumber() {
return classNumber;
}
public String getName() {
return name;
}
public char getSex() {
return sex;
}
public Integer getAge() {
return age;
}
public Student(Integer classNumber, String name, char sex, Integer age) {
super();
this.classNumber = classNumber;
this.name = name;
this.sex = sex;
this.age = age;
}
@Override
public String toString() {
return "班级编号:" + getClassNumber() + "\t姓名:" + getName() + "\t性别:" + sex + "\t年龄:" + age;
}
}
package comparator;
import java.util.Comparator;
import com.vince.Student;
public class StudentComparator implements Comparator<Student> {
@Override
public int compare(Student o1, Student o2) {
// TODO
if(o1.getAge() == o2.getAge()) {
return 0;
}
if(o1.getAge() >= o2.getAge()) {
return 1;
}else {
return -1;
}
}
}
package test;
import java.util.TreeSet;
import com.vince.Student;
import comparator.StudentComparator;
public class Test4 {
public static void main(String[] args) {
TreeSet<Student> treeSet = new TreeSet<>(new StudentComparator());
treeSet.add(new Student(1,"小明",'男',22));
treeSet.add(new Student(5,"小白",'男',20));
treeSet.add(new Student(3,"木子",'女',45));
treeSet.add(new Student(3,"木子",'女',45));
treeSet.add(new Student(7,"小绿",'女',32));
treeSet.add(new Student(1,"小明",'男',22));
for (Student student : treeSet) {
System.out.println(student);
}
}
}
- 总结:
比较器是把集合或数组的元素强行按照指定方法进行排序的对象,它是实现了Comparator接口类的实例。如果一个集合元素是可比较的(实现了Comparable接口),那么就具有了默认排序方法,比较器则是强行改变它默认的比较方式来进行排序。或者有的集合元素不可比较(没有实现Comparable接口),则可用比较器来实现动态的排序。
相同点:Comparable和Comparator可以按照指定方法,对对象实现动态的排序。他们实现排序的方法的返回值都是int类型,分为三种情况:1、0和-1。
不同点:Comparable的排序依赖的是compareTo方法,且参数只有一个。Comparator的排序依赖的是compare,传入参数有两个,可以通过匿名内部类或者单独实现。Comparator接口一般不会被集合元素类所实现,而是单独实现或者匿名内部类方式实现。