java中sort降序排序-sort数组有sort排序方法,但是它的用法有点复杂
引言
大家都知道,Array数组有sort排序方法,用法也很简单,直接Array.sort();调用就行,但是在ArrayList中,也有sort方法,但是它的用法有点复杂。
sort方法源码解析
首先我们在IDEA中按住Ctrl键点击sort方法去看它的源码。
出来的是这么一大堆东西,看不懂是不,我教你,复制这些绿色字体去百度翻译翻译一下(有时我们要学会借用工具)。
现在我们只需要了解它是用来干嘛的以及怎样去用它,所以我只截取了一小段。c–用于比较列表元素的比较器。null值表示应使用元素的自然排序。但是细心的我就发现,ArrayList的方法实现中只有一个传参为比较器的方法,没有传参为null的重载方法。这里我猜测,因为ArrayList中存储的都是引用类型,引用类型没法进行自然排序或者是它的排序规则需要你自己去定义。
基础数据封装类的排序
这里我用Integer举例
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
public class Text5_26 {
public static void main(String[]args){
List List=new ArrayList<>();
List.add(10);
List.add(12);
List.add(1);
List.add(13);
List.add(9);
List.sort(Comparator.comparingInt(o->o));
System.out.println(List);
}
}
这里我们实现了Comparator接口中的comparingInt方法,我们还是点进源码中然后百度翻译
从这里得知,我们只需从T中提取一个int类型的数据用于比较就行,提取的方法用到lambda表达式。关于lambda表达式呢,我们只需要记住,“->”左边是一个参数,右边是返回的值,返回值作为这个函数的传参。但是要记住一点,lambda表达式只能用于函数型接口,如果一个接口中有多个待实现的方法,lambda表达式就不能用了,它无法识别这个表达式到底实现的是哪个方法。
既然如此我们可以做一个小实验,验证是不是只需要从T中提取一个int类型的数据用于比较就行,我把引用类型改成Double,然后实现Comparator接口中的comparingInt方法再比较看能不能行。
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
public class Text5_26 {
public static void main(String[]args){
List List=new ArrayList<>();
List.add(10.5);
List.add(12.6);
List.add(1.4);
List.add(13.8);
List.add(9.6);
List.sort(Comparator.comparingInt(o-> (int)(o+0.5) ) );
System.out.println(List);
}
}
这里用上强制类型转换是可行的,当然,Double封装类也有自己的比较器方法叫作comparingDouble,使用方法同上。
到这里我可以暂时把比较器理解为是对排序的一种规范,它告诉sort方法,怎样算“大”,怎样应该排在前面。当然这只是我的理解,肯定不够全面。
自定义引用类型的排序
我们写的自定义引用类型的属性一般不止一个两个,那么我们又该怎么排序,按照哪个属性标准排呢。先写一个自定义类。
public class TextStu {
private String name;
private int age;
private double avg;
public TextStu(String name, int age, double avg) {
this.name = name;
this.age = age;
this.avg = avg;
}
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 double getAvg() {
return avg;
}
public void setAvg(double avg) {
this.avg = avg;
}
@Override
public String toString() {
return "TextStu{" +
"name='" + name + '\'' +
", age=" + age +
", avg=" + avg +
'}';
}
}
再给几个元素。
import java.util.ArrayList;
import java.util.List;
public class Text5_26 {
public static void main(String[]args){
List List=new ArrayList<>();
List.add(new TextStu("zhangsan",18,80.3));
List.add(new TextStu("lisi",19,69.9));
List.add(new TextStu("wangwu",17,70.1));
List.add(new TextStu("ahua",23,77.0));
List.add(new TextStu("xiewu",19,78.4));
System.out.println(List);
}
}
这时候再尝试去写sort方法。其实跟上面差不了太多,只是属性是私有的,需要通过get方法访问。
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
public class Text5_26 {
public static void main(String[]args){
List List=new ArrayList<>();
List.add(new TextStu("zhangsan",18,80.3));
List.add(new TextStu("lisi",19,69.9));
List.add(new TextStu("wangwu",17,70.1));
List.add(new TextStu("ahua",23,77.0));
List.add(new TextStu("xiewu",19,78.4));
System.out.println(List);
List.sort(Comparator.comparingInt(o->o.getAge()));
System.out.println(List);
}
}
这里其实可以写成方法引用,方法引用也是函数式接口的一种书写方法,这样子写更有逼格,但我不推荐,因为我不熟悉这种写法。lambda表达式的书写表示自己提供方法体,方法引用就是直接引用现成的方法。
但是,这种方法对String类型的不适用,因为String类型既不是基础数据类型也不是基础数据类型的包装类,它是引用类型。但我就是想比较一下怎么办呢,Comaraptor中提供了这样一个方法接口。
翻译一下
取重点:比较其两个参数的顺序。当第一个参数小于、等于或大于第二个参数时,返回负整数、零或正整数。我们还是用get方法访问私有属性。
import java.util.ArrayList;
import java.util.List;
public class Text5_26 {
public static void main(String[]args){
List List=new ArrayList<>();
List.add(new TextStu("zhangsan",18,80.3));
List.add(new TextStu("lisi",19,69.9));
List.add(new TextStu("wangwu",17,70.1));
List.add(new TextStu("ahua",23,77.0));
List.add(new TextStu("xiewu",19,78.4));
System.out.println(List);
List.sort(((o1, o2) -> {
return o1.getName().compareTo(o2.getName());
}));
System.out.println(List);
}
}
这里用到了String.compareTo方法,这是一个已经写好了的用于两个字符串比较的方法java中sort降序排序,它的源码很简单,应该是这篇文章中唯一不用百度翻译就能看懂的。
public int compareTo(String anotherString) {
int len1 = value.length;
int len2 = anotherString.value.length;
int lim = Math.min(len1, len2);
char v1[] = value;
char v2[] = anotherString.value;
int k = 0;
while (k < lim) {
char c1 = v1[k];
char c2 = v2[k];
if (c1 != c2) {
return c1 - c2;
}
k++;
}
return len1 - len2;
}
后来我又发现,开发java的这些大佬想的很周到。其实这种对自定义引用类型中字符串属性排序的方法又可以写成这样,这就与上文有异曲同工之妙了。
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
public class Text5_26 {
public static void main(String[]args){
List List=new ArrayList<>();
List.add(new TextStu("zhangsan",18,80.3));
List.add(new TextStu("lisi",19,69.9));
List.add(new TextStu("wangwu",17,70.1));
List.add(new TextStu("ahua",23,77.0));
List.add(new TextStu("xiewu",19,78.4));
System.out.println(List);
List.sort((Comparator.comparing(TextStu::getName)));
System.out.println(List);
}
}
所以,其实一般情况下写法有很多种,你可以选择最帅的那种。
总结:
到这里,我就总结出来了一些东西,使用ArrayList中的sort方法你需要传入一个比较器,这个比较器里的方法需要你完善。comparing、compaingInt、comparingDouble等方法需要你完善它的参数——从引用类型中抽取用于比较的属性java中sort降序排序,它的排序规则是定死的,属于是自然排序(从大到小或从小到大)。compareTo方法则是“万金油”,你需要完善它的整个方法体,但是它的排序规则是由用户定制的,属于定制排序,你只需要按照规范返回一个值就行了。打个比方:
public class Text5_26 {
public static void main(String[]args){
List List=new ArrayList<>();
List.add(new TextStu("zhangsan",18,80.3));
List.add(new TextStu("lisi",19,69.9));
List.add(new TextStu("wangwu",17,70.1));
List.add(new TextStu("ahua",23,77.0));
List.add(new TextStu("xiewu",19,78.4));
System.out.println(List);
List.sort(((o1, o2) -> {
if(o1.getAvg()==78.4){
return 1;
}else {
return Double.compare(o1.getAvg(), o2.getAvg());
}
}));
System.out.println(List);
}
}
我们可以“破坏”自然排序的规则,这里78.4永远是最大的。
这篇博客到此就结束了,如有不对请指出。