前言
今天某客户突然提出一个要求,要将公司某app里面的数据进行下排序,要求先按照类型排序,类型相同的按照文件名排序,想了想,如果自己写排序算法估计又要大半天而且保不准出一个bug直接gg,那估计得被客户吊起来打,所以查了下文档,发现在Collections类与Arrays类中都存在一个void sort(List<T> list)方法,可以直接对List进行升序排列,其中最关键的就是Comparable与Comparator接口,下面就来介绍下这个Java基础知识。
Collections.sort的使用
在介绍Comparable之前首先贴出一段代码介绍下Collections.sort的使用。
public class T {
public static void main(String[] args) {
List<Integer> arrays = getIntArray();
printArray("排序前", arrays);
Collections.sort(arrays);
printArray("排序后", arrays);
}
public static List<Integer> getIntArray() {
List<Integer> arrays = new ArrayList<Integer>();
Random random = new Random();
for (int i = 0; i < 15; i++) {
arrays.add(random.nextInt(10));
}
return arrays;
}
public static <T extends Comparable<? super T>> void printArray(String tag,
List<T> arrays) {
System.out.print(tag + ":");
for (T i : arrays) {
System.out.print(i.toString());
}
System.out.println("");
}
}
//输出为
//排序前:747456925001945
//排序后:001244455567799
从上面的代码可以看到,仅仅使用了一句Collections.sort(arrays);就将一组数字进行了升序排序,妈妈再也不用担心我纠结使用什么排序算法了。是不是很开心呢?
不过虽然简单一句话就进行了排序,但是万一客户觉得这样排序太没个性了,我需要奇数在前面,偶数在后面,然后分别降序排序,这个时候就该轮到Comparable接口出手了。
Comparable与Comparator
Comparable接口,功能和他的名字一样,仅仅负者比较,就像我们的几大排序算法一样,主要操作就是两两比较,然后互相交换位置而已,所以我们可以自己实现一个Comparable接口,创建我们自己的比较规则,从Collections.sort方法的定义中我们也可以看出,能被sort方法排序的list中的元素都实现了Comparable。
public static <T extends Comparable<? super T>> void sort(List<T> list)
在上面的例子中,Integer类已经实现了Comparable接口,所以可以直接使用sort(List<T> list)方法进行排序,但是对于我们自定义类型如果不实现Comparable接口,那么sort方法则会报错。大部分的Java自带数据类型都实现了Comparable接口。

要想自定义类型也能调用sort方法,或者想改变默认的排序规则,那么有两种方法,一种是调用sort(List<T> list,Comparator<? super T> c)方法,传入一个Comparator接口的实现类另一种就是直接sort(List<T> list),并让自定义类型实现Comparable接口。
使用Comparator接口进行排序
首先查看Comparator接口定义。
public interface Comparator<T> {
/**
* @param o1 the first object to be compared.
* @param o2 the second object to be compared.
* @return 返回 = 0 表示o1 == o2
返回 > 0 表示o1 > 02
返回 < 0 表示o1 < 02
* @throws NullPointerException if an argument is null and this
* comparator does not permit null arguments
* @throws ClassCastException if the arguments' types prevent them from
* being compared by this comparator.
*/
int compare(T o1, T o2);
}
下面就使用sort(List<T> list,Comparator<? super T> c)方法来实现上面的问题,要求奇数在偶数前面,并且分别都是升序排列。
public class T {
public static void main(String[] args) {
List<Integer> arrays = getIntArray();
printArray("排序前", arrays);
Collections.sort(arrays, new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
if ((o1 % 2 == 0 && o2 % 2 == 0)
|| (o1 % 2 == 1 && o2 % 2 == 1)) {
return o1 - o2;
}
return o1 % 2 == 0 ? 1 : -1;
}
});
printArray("排序后", arrays);
}
public static List<Integer> getIntArray() {
List<Integer> arrays = new ArrayList<Integer>();
Random random = new Random();
for (int i = 0; i < 15; i++) {
arrays.add(random.nextInt(10));
}
return arrays;
}
public static <T extends Comparable<? super T>> void printArray(String tag,
List<T> arrays) {
System.out.println(tag + ":");
for (T i : arrays) {
System.out.print(i.toString());
}
System.out.println("");
}
}
//输出
//排序前:
//824836845338147
//排序后:
//133357244468888
可以看到,使用了Collections.sort(List<T> list,Comparator<? super T> c)方法,并且Comparator接口的实现为,如果同为奇数偶数则直接比较大小,如果一奇一偶,则返回奇数那个较大。
使用Comparable接口进行排序
同样先查看下Comparable接口的定义。
public interface Comparable<T> {
/**
* @param o the object to be compared.
* @return 返回 = 0 表示o1 == o2
返回 > 0 表示o1 > 02
返回 < 0 表示o1 < 02
* @throws NullPointerException if the specified object is null
* @throws ClassCastException if the specified object's type prevents it
* from being compared to this object.
*/
public int compareTo(T o);
}
下面就使用sort(List<T> lis)方法来实现自定义类型进行排序,要求,先按照年级排序,同年级的按照姓名字母排序。
public class T {
public static void main(String[] args) {
List<Student> students = new ArrayList<>();
students.add(new Student(2017, "小白"));
students.add(new Student(2014, "AAA"));
students.add(new Student(2013, "小明"));
students.add(new Student(2014, "ABC"));
students.add(new Student(2016, "123"));
students.add(new Student(2016, "!@"));
students.add(new Student(2013, "阿里"));
students.add(new Student(2013, "AADB"));
students.add(new Student(2015, "!@#里"));
students.add(new Student(2013, "aaa"));
printArray("排序前", students);
Collections.sort(students);
printArray("排序后", students);
}
public static <T extends Comparable<? super T>> void printArray(String tag,
List<T> arrays) {
System.out.println(tag + ":");
for (T i : arrays) {
System.out.print(i.toString());
}
System.out.println("");
}
public static class Student implements Comparable<Student> {
// 年级
public int grade;
// 姓名
public String name;
public Student(int grade, String name) {
this.grade = grade;
this.name = name;
}
@Override
public int compareTo(Student other) {
if (grade == other.grade) {
return name.compareToIgnoreCase(other.name);
}
return grade - other.grade;
}
@Override
public String toString() {
StringBuffer sb = new StringBuffer();
sb.append("年级:" + grade);
sb.append(" name:" + name);
sb.append("\n");
return sb.toString();
}
}
}
程序输出结果为:
排序前: 年级:2017 name:小白 年级:2014 name:AAA 年级:2013 name:小明 年级:2014 name:ABC 年级:2016 name:123 年级:2016 name:!@ 年级:2013 name:阿里 年级:2013 name:AADB 年级:2015 name:!@#里 年级:2013 name:aaa 排序后: 年级:2013 name:aaa 年级:2013 name:AADB 年级:2013 name:小明 年级:2013 name:阿里 年级:2014 name:AAA 年级:2014 name:ABC 年级:2015 name:!@#里 年级:2016 name:!@ 年级:2016 name:123 年级:2017 name:小白