目录
前言:
一维数组降序:
方法1.Comparator接口:
代码实现:
方法2.Collections.reverseOrder():
代码实现:
二维数组排序:
代码如下:
List<>排序:
代码如下:
自定义类型比较排序:
按照年龄逆序排序:
按照姓名升序排序:
lambda表达式简写:
一维数组逆序代码:
二维数组排序代码:
List<>排序代码:
自定义类型排序:
结语:
前言:
由于最近刷一些比赛真题时,发现有一些题要先排序一下后面才能用贪心之类的算法解决,在比赛上面自己实现一个排序算法有点浪费时间(当然不是指冒泡插入之类的简单排序,太慢了?),考虑到java中Arrays类中有sort方法我们可以引用sort来排序,升序简单那降序呢,一维数组会排序那二维数组和List<>呢? 本文章就是为了解决这些问题,希望对友友有所帮助。???
我相信来看这个的一般都是有急用吧???(作者曾经也是),如果很急的话直接看代码实现,直接模仿着写即可,其他的都是一些知识点的讲解。
要想使用sort排序,排序的对象必须实现comparable接口才行,由于Comparable不太灵活故本文章不做详细介绍。
一位数组的基本类型sort方法都能排序(升序)。
可以说的是一维数组降序和二维数组排序都是通过如下sort的重载方法即传入一个比较器(参数是泛型的不能是基本类型)。
一维数组降序:
声明:为了方便叙述下面采用int和Integer进行叙述其他类似。
经过多次尝试和查阅许多资料得出:要想把一维数组逆序如果是基本类型的话要把它变成包装类,
基本类型实现不了。
方法1.Comparator接口:
实现Comparator接口可以说是最常用的一种自定义排序操作了,它比Comparable更加灵活,想要根据什么比较直接自己实现就行,下面我们就开始对它的介绍?:
Comparator是一个接口,既然接口那么我们实现它必须要重写它的抽象方法compare,必须要重写这一个(这个接口只有这一个方法)。
如果不实现就是出现如下错误。
实现比较器Comparator接口,上面< T >代表这是一个泛型(如果对泛型还不是很了解的话也没关系我们可以先会用就行),注意:泛型只能接受类,所有的基本数据类型必须使用包装类!,这就代表了我们要实现一维数组的逆序必须要把基本类型换成其包装类才行。否则会报如下错误。
代码实现:
import java.util.Arrays;import java.util.Comparator;class cmp implements Comparator<Integer>{ @Override public int compare(Integer o1,Integer o2){ return o2 - o1; }}public class Test1 { public static void main(String[] args) { Integer[] nums = {1,2,3,4,5}; Arrays.sort(nums,new cmp()); for(int i = 0;i < nums.length;i++){ System.out.print(nums[i] + " "); } }}
效果如下:
如果想要升序的话就 o1 - o2.
方法2.Collections.reverseOrder():
这个我是从别人那里看到的,因为这个好像整洁一点故也把他写进来(还是推荐Comparator
),源码如下,我们可以看到其实是传入一个比较器(Comparator)。注意要importCollections这个类。其源代码如下图。
代码实现:
import java.util.Arrays;import java.util.Collections;public class Main{ public static void main(String[] args) { Integer[] nums = {1,2,3,4,5}; Arrays.sort(nums, Collections.reverseOrder()); for(int i = 0;i < nums.length;i++){ System.out.print(nums[i] + " "); } }}
不过很可惜的是这样像int这样的基本类型还是不行?。
二维数组排序:
二维数组这里只介绍Comparator方法,这个是最常用的。
代码如下:
是不是非常神奇,这其实说明int[]在内部可能是把它当作类来看的。
import java.util.Arrays;import java.util.Comparator;class cmp implements Comparator<int[]> { @Override public int compare(int[] o1,int[] o2){ return o1[0] - o2[0]; }}public class Main { public static void main(String[] args) { int[][] nums = {{1,7},{2,6},{3,9},{8,2},{2,5}}; Arrays.sort(nums,new cmp()); for(int i = 0;i < nums.length;i++){ for(int j = 0;j < nums[i].length;j++) { System.out.print(nums[i][j] + " "); } System.out.println(); } }}
结果如下我们是按照一行的第一个元素进行排序,显然这样做我们的结果是对的???
相信到这里友友们是不是发现新大陆了呢,按照每行的第几个数组来排序就改对应的o1和o2的下标即可如果想要逆序的话只需把o1 - o2 改为 o2 - o1即可。
多维类似,因为用的比较少故这里不再展开☆*: .。. o(≧▽≦)o .。.:*☆。
List<>排序:
在刷力扣的友友应该有这方面的需求,这类题目一般都是深搜DFS和回溯,要你返回这样的类型或者题目给你这样的类型。不先排个序的话会非常麻烦???。这个List排序和上面的数组排序类似,这里写下是因为可能有的友友不知道List类中本来就有个sort方法可以用来排序List<>.
下面图片来自List官方文档,要想排序List<>就要调用List类中的sort方法,万幸的是它也可以传入比较器这意味这通用性会更强。
要想实现List.sort()排序就要创建一个比较类cmp(名字随便),cmp实现Comparator接口,在接口中传入List<>中的数据类型,注意不是传入List<Integer>可能有的友友会这么认为,但这是错误的❌。
代码如下:
import java.util.Comparator;import java.util.List;import java.util.ArrayList;class cmp implements Comparator<Integer>{ @Override public int compare(Integer o1, Integer o2) { return o1 - o2; }}public class Test1 { public static void main(String[] args) { List<Integer> ret = new ArrayList<>(); ret.add(4); ret.add(3); ret.add(2); ret.add(1); ret.sort(new cmp()); for(Integer x:ret){ System.out.print(x + " "); } }}
其运行结果如下:显然正确???
自定义类型比较排序:
声明:为了方便叙述我们自定义一个Person类里面有int类型的年龄,String类型的姓名。
在更多情况下我们还是想直接用sort来排序自定义类型,下面我给出java对象比较的三种方式如下图:
覆写的方法 | 说明 |
Object.equals | 因为所有类都是继承自Object的,所以直接覆写即可,不过只能比较相等与否。 |
Comparable.compareTo | 需要手动实现接口,侵入性比较强,但一旦实现,每次用该类都有顺序,属于内部顺序。 |
Comparator.compare | 需要实现一个比较器对象,对待比较类的侵入性弱,但对算法代码实现侵入性强。 |
equals不是用在sort中的,只是如果想要就自定义类型使用>,<,==,的话就必须要重写equals方法。
在自定义类中基本用的都是自己实现一个比较器故下面不讲Comparable(只能比较一个,后续如果要修改很麻烦不方便),都是使用Comparator。
由于本文章主要讲解自定义类型sort排序,其它的一些细节问题不过多描述还请见谅❤️。
如果直接用sort的话编译能通过但会报如下错误,右边为Person类。
按照年龄逆序排序:
代码如下:
import java.util.Arrays;import java.util.Comparator;class Person{ int age; String name; public Person(int age,String name){ this.age = age; this.name = name; } @Override public String toString() { return "Person{" + "age=" + age + ", name='" + name + '\'' + '}'; }}class cmp implements Comparator<Person>{ public int compare(Person o1,Person o2){ return o2.age - o1.age; }}public class Test2 { public static void main(String[] args) { Person person1 = new Person(1,"cc"); Person person2 = new Person(3,"bb"); Person person3 = new Person(2,"aa"); Person[] array = new Person[3]; array[0] = person1; array[1] = person2; array[2] = person3; Arrays.sort(array,new cmp()); for(int i = 0;i < array.length;i++){ System.out.println(array[i]); } }}
效果如下:
之所以能println出来这样是因为我们在Person类中重写了toString方法。
升序就不用说了。
按照姓名升序排序:
为了使文章更加简洁下面只给出比较器,友友们自己替换一下即可。name是String类型要比较大小直接调用compareTo方法即可。
class cmp implements Comparator<Person>{ public int compare(Person o1,Person o2){ return o1.name.compareTo(o2.name); }}
结果如下:
lambda表达式简写:
这个lambada表达式简写是我在看别人题解时看到的,说实话第一次看到有点震惊,如果对这个很熟悉的话用sort来实现各种排序将写的非常快。由于文章篇幅有限下面直接给出用法不解释原理,大家可以先模仿等后续学到lambada表达式就水到渠成了???
下面是lambada的语法实在不想看的话可以跳过会用就行?
Lambada表达式的语法:
基本语法: (parameters) -> expression 或 (parameters) ->{ statements}
Lambda表达式由三部分组成:
(1)paramaters:类似方法中的形参列表,这里的参数是函数式接口里的参数。这里的参数类型可以明确的声明也可不声明而由JVM隐含的推断。另外当只有一个推断类型时可以省略掉圆括号。
(2)->:可理解为“被用于”的意思。
(3)方法体:可以是表达式也可以是代码块,是函数式接口里方法的实现。代码块可返回一个值或者什么都不返回,这里的代码块等同于方法的方法体。如果是表达式,也可以返回一个值或者什么都不反回。
一维数组逆序代码:
public class Test4 { public static void main(String[] args) { Integer[] nums = {1,7,4,2,9,6,4}; Arrays.sort(nums,(o1,o2)-> o2 - o1); for(int i = 0;i < nums.length;i++){ System.out.print(nums[i] + " "); } }}
结果如下:
二维数组排序代码:
import java.util.Arrays;public class Test5 { public static void main(String[] args) { int[][] nums = {{1,3},{2,7},{6,7},{4,1},{3,9}}; Arrays.sort(nums,(o1,o2)->o1[0] - o2[0]); for(int i = 0;i < nums.length;i++){ for(int j = 0;j < nums[i].length;j++){ System.out.print(nums[i][j] + " "); } System.out.println(); } }}
效果如下:
List<>排序代码:
import java.util.ArrayList;import java.util.List;public class Test6 { public static void main(String[] args) { List<Integer> ret = new ArrayList<>(); ret.add(1); ret.add(2); ret.add(3); ret.add(4); ret.sort((o1,o2)->o2 - o1); for(Integer x:ret){ System.out.print(x + " "); } }}
结果如下:
自定义类型排序:
这个有点多且上面代码给过了这里直接给图片啦!
到这已经把Java当中sort常用的排序已经全部给出,说实话整理出来还是挺不容易的???,查阅资料等等这篇博客我整理了将近一周的时间希望对大家有所帮助❤️❤️❤️。
结语:
其实写博客不仅仅是为了教大家,同时这也有利于我巩固知识点,和做一个学习的总结,由于作者水平有限,对文章有任何问题还请指出,非常感谢。如果大家有所收获的话还请不要吝啬你们的点赞收藏和关注,这可以激励我写出更加优秀的文章。