一,可能对于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接口。