java Comparator 排序和二次排序 作者:马育民 • 2021-12-25 09:15 • 阅读:10468 # 说明 `java.util.Comparator` 类似 `Comparable` ,可以实现 **排序** 功能 ### 应用场景 - 某个类 **不实现** `Comparable` 接口,**又要进行比较** - 某个类 实现了 `Comparable` 接口,但是开发者认为其比较方式并不是自己想要,需要 **临时** 改用自己的排序规则。 如:List,其元素是 `Integer` 型,默认 **从小到大排序**,但要改成 **从大到小排序** # 方法 `Comparator`接口里面有一个 `compare` 方法,如下: ``` int compare(T o1, T o2); ``` **形参:** 方法有两个参数 `T o1` 和 `T o2`,是 **泛型** 的表示方式,分别表示待比较的两个对象。 **注意:**在集合中(如:数组、List),`o1` 表示 **后一个元素**,`o2` 表示 **前一个元素**,如下图: [![](http://65242847.gitee.io/pic/java/Snipaste_2021-12-25_10-32-54.png)](http://65242847.gitee.io/pic/java/Snipaste_2021-12-25_10-32-54.png) **返回值:**方法返回值是int,有三种情况: - 正整数,**不会改变** 这2个元素的位置 - 负整数,**交换** 这2个元素的位置 - 0,表示 o1等于o2,**不会改变** 这2个元素的位置 返回值表示 **排序规则** ### 排序规则-正序(从小到大) - o1(后一个元素)**大于** o2(前一个元素),返回 **正整数** - o1(后一个元素)**小于** o2(前一个元素),返回 **负整数**,**会交换这2个元素的位置** [![](http://65242847.gitee.io/pic/java/Snipaste_2021-12-25_10-40-32.png)](http://65242847.gitee.io/pic/java/Snipaste_2021-12-25_10-40-32.png) ### 排序规则-倒序(从大到小) - o2(前一个元素)**大于** o1(后一个元素),返回 **正整数** - o2(前一个元素)**小于** o1(后一个元素),返回 **负整数**,**会交换这2个元素的位置** # 例子-int 数组 **从小到大排序**,即:**正序** 这里只是为了演示,其实对于 `int` 型数组,不需要实现 `Comparator`,因为数字型本身就可以排序 ``` package test; import java.util.*; public class Std_Comparator_array { public static void main(String[] args) { Integer[] array=new Integer[]{1,3,2}; Arrays.sort(array,new MyComparator()); System.out.println(Arrays.toString(array)); } static class MyComparator implements Comparator { /** * * @param o1 后一个元素 * @param o2 前一个元素 * @return */ @Override public int compare(Integer o1, Integer o2) { int ret=0; if(o2 > o1){ ret=-1; }else if(o2 < o1){ ret=1; }else{//等于 ret=0; } return ret; } } } ``` ### 返回元素相减,简化操作 **从小到大排序**,即:**正序**,返回 `后一个元素(第一个形参) - 前一个元素(第二个形参)` ``` package test; import java.util.*; public class Std_Comparator_array { public static void main(String[] args) { Integer[] array=new Integer[]{1,3,2}; Arrays.sort(array,new MyComparator()); System.out.println(Arrays.toString(array)); } static class MyComparator implements Comparator { /** * * @param o1 后一个元素 * @param o2 前一个元素 * @return */ @Override public int compare(Integer o1, Integer o2) { int ret = o1 - o2; return ret; } } } ``` # 例子-int List 对于 `int` 型List,已经实现了 **从小到大排序**,但我们要改成 **从大到小排序**,即:**倒序** ``` package test; import org.apache.flink.api.java.tuple.Tuple2; import java.util.*; public class Std_Comparator_list_daoxu { public static void main(String[] args) { List list=new ArrayList(); list.add(1); list.add(3); list.add(2); list.sort(new MyComparator()); // list本身排序 // Collections.sort(list,new MyComparator()); //Collections.sort()排序 System.out.println(Arrays.toString(list.toArray())); } static class MyComparator implements Comparator { /** * * @param o1 后一个元素 * @param o2 前一个元素 * @return o1大于o2,返回正整数;o1小于o2,返回负整数;返回0,表示等于 */ @Override public int compare(Integer o1, Integer o2) { int ret=0; if(o2 < o1){ ret=-1; }else if(o2 > o1){ ret=1; }else{//等于 ret=0; } return ret; } } } ``` # 例子:对象类型 假设某类没有实现 `Comparable` 接口,但是又想进行比较 或者 实现了 `Comparable` 接口,但是开发者认为其比较方式并不是自己想要,需要 **临时** 改用自己的排序规则 ### 根据年龄比较 有 `Student` 类,没有实现 `Comparable` 接口,但又想根据 **年龄** 进行比较 **Student类:** ``` package test; public class Student { private String name; private int age; private int length; public Student(String name, int age,int length) { this.name = name; this.age = age; this.length = length; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public int getLength() { return length; } public void setLength(int length) { this.length = length; } @Override public String toString() { // TODO Auto-generated method stub return name+","+age+","+length; } } ``` **主类** ``` package test; import java.util.*; public class Std_Comparator_list_Student { public static void main(String[] args) { Student std=new Student("李雷",20,182); Student std2=new Student("lucy",16,168); Student std3=new Student("lucy",16,167); Student std4=new Student("韩梅梅",25,165); Student std5=new Student("张三",16,185); List list=new ArrayList(); list.add(std); list.add(std2); list.add(std3); list.add(std4); list.add(std5); // list.sort(new MyComparator()); // list本身排序 Collections.sort(list,new MyComparator()); //Collections.sort()排序 System.out.println(Arrays.toString(list.toArray())); } static class MyComparator implements Comparator { /** * * @param o1 后一个元素 * @param o2 前一个元素 * @return */ @Override public int compare(Student o1,Student o2) { int res=0; if( o1.getAge() < o2.getAge()){ res=-1; }else if(o1.getAge() > o2.getAge()){ res=1; }else{//相等 res=0; } return res; } } } ``` # 二次排序 对于上面的例子,当 **年龄** 相同时,**身高从大到小排序** 修改测试类,进行二次排序 ``` package test; import java.util.*; public class Std_Comparator_list_Student2 { public static void main(String[] args) { Student std=new Student("李雷",20,182); Student std2=new Student("lucy",16,168); Student std3=new Student("lucy",16,167); Student std4=new Student("韩梅梅",25,165); Student std5=new Student("张三",16,185); List list=new ArrayList(); list.add(std); list.add(std2); list.add(std3); list.add(std4); list.add(std5); // list.sort(new MyComparator()); // list本身排序 Collections.sort(list,new MyComparator()); //Collections.sort()排序 System.out.println(Arrays.toString(list.toArray())); } static class MyComparator implements Comparator { /** * * @param o1 后一个元素 * @param o2 前一个元素 * @return */ @Override public int compare(Student o1,Student o2) { int res=0; if( o1.getAge() < o2.getAge()){ res=-1; }else if(o1.getAge() > o2.getAge()){ res=1; }else{//相等 // res=0; //二次排序 if(o1.getLength()>o2.getLength()){ res=-1; }else if(o1.getLength() < o2.getLength()){ res=1; }else{ res=0; } } return res; } } } ``` 原文出处:http://malaoshi.top/show_1IX2TE5dbYvz.html