java进阶|比较器Comparable和Comparator
程序员文章站
2022-03-10 17:08:01
...
一,可能对于java的coder来说,这个点很简单,但对于我来说又是很难,想写这篇文章也是很久了,今天就以自己的理解来看下这两个接口,首先我们先看下Comparable接口的结构图。
这个比较接口只包含了一个compareTo()方法的接口,Comparable是一个排序接口,当我们定义的类实现了该接口,就说明了该类支持排序。
我们通过x.compareTo(y)来比较x和y的大小。若返回负数,则x比y小,若返回0,则x=y,若返回整数,则x大于y。
二,这里,自己去编写一个静态内部类来进行测试Comparable接口的使用。
package com.wpw.springbootjuc.java8.map;
import com.google.common.collect.Lists;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import lombok.extern.slf4j.Slf4j;
import java.util.Collections;
import java.util.List;
/**
* Comparable接口
*
* @author wpw
*/
@Slf4j
public class ComparableTest {
public static void main(String[] args) {
List<Person> personList = Lists.newArrayList();
getPersonList(personList);
System.out.println("Before Sort");
acceptAndPrint(personList);
Collections.sort(personList);
System.out.println("After Sort");
acceptAndPrint(personList);
}
private static void acceptAndPrint(List<Person> personList) {
personList.stream().forEach(x -> {
System.out.println(String.format("Id:%d,Name:%s,Age:%d", x.getId(), x.getName(), x.getAge()));
});
System.out.println();
}
/**
* @return 数据集合,这里就简单模拟一下
*/
private static void getPersonList(List<Person> personList) {
personList.add(Person.builder().build().setId(3).setName("John").setAge(18));
personList.add(Person.builder().build().setId(1).setName("Tom").setAge(20));
personList.add(Person.builder().build().setId(2).setName("Marry").setAge(21));
}
}
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Accessors(chain = true)
class Person implements Comparable<Person> {
private Integer id;
private String name;
private Integer age;
/**
* @param o 待比较的对象
* @return 比较的值-1,0,1
*/
@Override
public int compareTo(Person o) {
return this.id - o.id;
}
}
排序前后输出的结果信息:
Before Sort
Id:3,Name:John,Age:18
Id:1,Name:Tom,Age:20
Id:2,Name:Marry,Age:21
After Sort
Id:1,Name:Tom,Age:20
Id:2,Name:Marry,Age:21
Id:3,Name:John,Age:18
三,接下来看下Comparator接口的结构图,这就是一个函数式接口,函数式接口就是只有一个方法,但是它可以有其它的默认方法。
四,下面的这张图就是Comparator接口包含的所有方法,大部分的都是default方法。
这里编写了一个示例程序用于测试Comparator接口的使用,Comparator为比较器接口,若要实现某个本身不支持排序的类,可以通过定义一个Comparator接口来实现类的排序。
package com.wpw.springbootjuc.java8.map;
import com.google.common.collect.Lists;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
/**
* Comparator接口
*
* @author wpw
*/
public class ComparatorTest {
public static void main(String[] args) {
List<Student> studentList = Lists.newArrayList();
getStudentList(studentList);
System.out.println("Before Sort");
acceptAndPrint(studentList);
Collections.sort(studentList, new MyComparator());
System.out.println("After Sort");
acceptAndPrint(studentList);
}
private static void acceptAndPrint(List<Student> studentList) {
studentList.stream().forEach(x -> {
System.out.println(String.format("Id:%d,Name:%s,Age:%d", x.getId(), x.getName(), x.getAge()));
});
System.out.println();
}
/**
* @return 数据集合,这里就简单模拟一下
*/
private static void getStudentList(List<Student> studentList) {
studentList.add(Student.builder().build().setId(3).setName("John").setAge(18));
studentList.add(Student.builder().build().setId(1).setName("Tom").setAge(20));
studentList.add(Student.builder().build().setId(2).setName("Marry").setAge(21));
}
@AllArgsConstructor
@NoArgsConstructor
@Data
@Builder
@Accessors(chain = true)
static class Student {
private Integer id;
private String name;
private Integer age;
}
/**
* 自定义比较器接口
*/
static class MyComparator implements Comparator<Student> {
@Override
public int compare(Student o1, Student o2) {
return o1.id - o2.id;
}
@Override
public boolean equals(Object obj) {
return super.equals(obj);
}
}
}
五,以上就是Comparable和Comparator接口都是用来实现集合中元素的比较和排序的,当我们自己定义的一个类需要进行排序时,就要考虑实现Comparable或者Comparator接口,这样就可以根据指定的属性进行排序。
六,何时使用Comparable接口,何时使用Comparator接口?当我们在对要排序的排序规则比较固定,则考虑使用Comparable接口,若要对排序的类的排序规则是经常变化的,那我们就考虑使用Comparator接口。