前言
今天某客户突然提出一个要求,要将公司某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:小白