Java使用lambda自定义Arrays.sort排序规则说明
目录
- lambda自定义Arrays.sort排序规则
- 1.类间排序
- 2.使用比较器(comparator)作为sort的参数(用于单个类型的排序)
- 补充一下
- Arrays.sort()的一些用法
- 1.对指定T型数组按指定数值升序排序
- 2.对指定T型数组的指定范围按指定数值升序排序
- 3.根据指定比较器产生的顺序对指定对象数组进行排序
lambda自定义Arrays.sort排序规则
1.类间排序
首先注意默认排规则,当使用sort(Objetc[] a)来进行对象的自然排序,该对象必需实现Compareable接口,重写compareableTo方法,并一般在此方法中定义这3种返回值(1,0,-1)来进行排序标准的确认。
- return 1 时,按照从小到大排序 (也可以是2,3.....正数)
- return 0 时,原位置不动
- return-1 时,按照从大到小排序
public class Person implements Comparable<Employee> { private String name; private int age; public Person() { } public Person(String name, int age) { this.name = name; this.age = age; } /* * Compares person by age * @param other another Person object * return a negative value if this employee has a lower age than * otherObject , 0 if the age are the same, a positive value otherwise */ public int compareTo(Person other) { return Integer.compare(age, other.age); } }
2.使用比较器(comparator)作为sort的参数(用于单个类型的排序)
// 正常方式 Arrays.sort(arr, new Comparator<int[]>() { public int compare(int[] a, int[] b) { return a[0]-b[0]; } });
// lambda方式 Integer[] numsArr = new Integer[10]; Arrays.sort(numsArr, (x, y) -> { int sx = 10, sy = 10; while (x >= sx) { sx *= 10; } while (y >= sy) { sy *= 10; } return (int)(sx * y + y - sy * x - x); });
需要注意传入数组必须是对象类型
补充一下
注意:Arrays.sort()使用的是双轴快排:
1.对于很小的数组(长度小于27),会使用插入排序。
2.选择两个点P1,P2作为轴心,比如我们可以使用第一个元素和最后一个元素。
3.P1必须比P2要小,否则将这两个元素交换,现在将整个数组分为四部分:
(1)第一部分:比P1小的元素。
(2)第二部分:比P1大但是比P2小的元素。
(3)第三部分:比P2大的元素。
(4)第四部分:尚未比较的部分。
在开始比较前,除了轴点,其余元素几乎都在第四部分,直到比较完之后第四部分没有元素。
4.从第四部分选出一个元素a[K],与两个轴心比较,然后放到第一二三部分中的一个。
5.移动L,K,G指向。
6.重复 4 5 步,直到第四部分没有元素。
7.将P1与第一部分的最后一个元素交换。将P2与第三部分的第一个元素交换。
8.递归的将第一二三部分排序。
对于基本类型的数组如int[], double[], char[] ,Arrays类只提供了默认的升序排列,没有降序,需要传入自定义比较器,使用Arrays.sort(num,c),传入一个实现了Comparator接口的类的对象c。
逆序排列:
Arrays.sort(num,new Comparator<Integer>(){ public int compare(Integer a, Integer b){ return b-a; } });
Compare函数:
Compares its two arguments for order. Returns a negative integer,zero, or a positive integer as the first argument is less than, equalto, or greater than the second.
- 1:前面的数>后面的数,是降序(从大到小)排列,如果想要改为升序排列,就需要返回1
- -1:前面的数<后面的数,是升序(从小到大)排列,不改变位置就返回-1;
- 0:二者相等,不进行交换,也就不排序。但是要根据题目来判断返回什么。如果数组是无序的,不能直接返回0。若保证升序排列,要返回o1-o2,降序则o2-o1。
- return 0:不交换位置,不排序
- return 1:交换位置
- return -1:不交换位置
- return o1-o2:升序排列
- return o2-o1:降序排列
compare方法中,写成return o1.compareTo(o2) 或者 return o1-o2表示升序;(2)写成return o2.compareTo(o1) 或者return o2-o1表示降序
Arrays.sort()的一些用法
Arrays.sort()重载了四类方法
sort(T[] a)
:对指定T型数组按数字升序排序。sort(T[] a,int formIndex, int toIndex)
:对指定T型数组的指定范围按数字升序排序。sort(T[] a, Comparator c)
:根据指定比较器产生的顺序对指定对象数组进行排序。sort(T[] a, int formIndex, int toIndex,Comparator c)
:根据指定比较器产生的顺序对指定对象数组的指定对象数组进行排序。
参数说明:查看源码就知道重载的数据类型包括 Object 一共有八个,其他七个就是基本类型: int , long , short , char , byte , float , double .
1.对指定T型数组按指定数值升序排序
int[] ints = new int[]{12, 4, 6, 7, 2, 8, 3, 9};// 按 数字 char[] chars = new char[]{'a', 'c', 'b', 'i', '+'};// 按 ascii 码 byte[] bytes = new byte[]{7, 5, 6, 10, -1};// 按 字节数 Arrays.sort(ints); Arrays.sort(chars); Arrays.sort(bytes); System.out.println(Arrays.toString(ints)); // 结果 :[2, 3, 4, 6, 7, 8, 9, 12] System.out.println(Arrays.toString(chars)); // 结果 :[+, a, b, c, i] System.out.println(Arrays.toString(bytes)); // 结果 :[-1, 5, 6, 7, 10]
2.对指定T型数组的指定范围按指定数值升序排序
int[] ints = new int[]{12, 4, 6, 7, 2, 8, 3, 9};// 按 数字 char[] chars = new char[]{'a', 'c', 'b', 'i', '+'};// 按 ascii 码 byte[] bytes = new byte[]{7, 5, 6, 10, -1};// 按 字节数 Arrays.sort(ints, 2, 5); Arrays.sort(chars, 2, 5); Arrays.sort(bytes, 2, 5); System.out.println(Arrays.toString(ints)); // 结果 :[12, 4, 2, 6, 7, 8, 3, 9] System.out.println(Arrays.toString(chars)); // 结果 :[a, c, +, b, i] System.out.println(Arrays.toString(bytes)); // 结果 :[7, 5, -1, 6, 10]
3.根据指定比较器产生的顺序对指定对象数组进行排序
(1) 一维数组降序排序
这里用降序演示一下;
/*注意,要想改变默认的排列顺序,不能使用基本类型(int,double, char) 而要使用它们对应的包装类*/ Integer[] ints = new Integer[]{12, 4, 6, 7, 2, 8, 3, 9}; Arrays.sort(ints, Collections.reverseOrder()); System.out.println(Arrays.toString(ints)); // 结果 :[12, 9, 8, 7, 6, 4, 3, 2]
也可以使用自定义规则
Arrays.sort(ints, new Comparator<Integer>() { @Override public int compare(Integer o1, Integer o2) { return o2 - o1; } }); // lambda 表达式 Arrays.sort(ints, (o1, o2) -> o2 - o1);
(2)二维数组按一维数组排序 升序
PS:这里提一下如果是 Integer数组 比较相等时用 equals 而不是用 == 。至于为什么请看 == 和 equals 的区别
int[][] nums=new int[][]{{1,3},{1,2},{5,1},{4,5},{3,3}}; //方法一 Arrays.sort(nums,new Comparator<int[]>(){ @Override public int compare(int[] a,int[] b){ // 当第一维相等时比较第二维的 if(a[0] == b[0]){ return a[1]-b[1]; }else{ return a[0]-b[0]; } } }); // 方法二,使用 lambda 表达式 Arrays.sort(nums,(a,b) -> a[0] == b[0] ? a[1]-b[1] : a[0]-b[0]); for (int[] num : nums) { System.out.print(Arrays.toString(num)); } // 结果 : [1, 2][1, 3][3, 3][4, 5][5, 1]
(3)二维数组按二维数组排序 升序
int[][] nums=new int[][]{{1,3},{1,2},{5,1},{4,5},{3,3}}; //方法一 Arrays.sort(nums,new Comparator<int[]>(){ @Override public int compare(int[] a,int[] b){ // 当第二维相等时比较第一维的 if(a[1] == b[1]){ return a[0]-b[0]; }else{ return a[1]-b[1]; } } }); // 方法二,使用 lambda 表达式 Arrays.sort(nums,(a,b) -> a[1] == b[1] ? a[0]-b[0] : a[1]-b[1]); for (int[] num : nums) { System.out.print(Arrays.toString(num)); } // 结果 : [5, 1][1, 2][1, 3][3, 3][4, 5]
(4)二维数组降序
对调返回值哪里的顺序
也就是:
// 按第一维降序 if(a[0].equals(b[0]){ return b[1]-a[1]; }else{ return b[0]-a[0]; } // 结果 : [5, 1][4, 5][3, 3][1, 3][1, 2]
(5)类的比较
其实这个方法最重要的还是类对象的比较
由于我们可以自定义比较器,所以我们可以使用策略模式,使得在运行时选择不同的算法
这里就不用代码说明了,就是根据指定比较器产生的顺序对指定对象数组的指定对象数组进行排序。
以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。