当前位置: 首页 > 科技观察

Java中List排序的三种方法!

时间:2023-03-14 22:17:27 科技观察

作者|王磊来源|Java中文社区(ID:javacn666)请联系授权(微信ID:GG_Stone)转载,在某些特殊场景下,我们需要对Java程序中的List集合进行排序。比如所有用户的列表是从第三方接口获取的,但是这个列表默认是按照用户数从小到大排序的,而我们的系统需要按照用户的年龄从大到小排序。这时候,我们需要对排序的List集合进行自定义的排序操作。List排序常用的三种方式:使用Comparable排序;使用Comparator进行排序;如果是JDK8以上的环境,也可以使用Stream进行排序。下面我们来看一下各种排序方式的具体实现。1.使用Comparable排序根据本文设计的场景,我们需要创建一个包含用户列表的List集合,并按照年龄从大到小排序。具体实现代码如下:publicclassListSortExample{publicstaticvoidmain(String[]args){//创建并初始化ListListlist=newArrayList(){{add(newPerson(1,30,"北京"));add(newPerson(2,20,"西安"));add(newPerson(3,40,"上海"));}};//使用Comparable自带的规则进行排序Collections.sort(list);//打印列表集合list.forEach(p->{System.out.println(p);});}}//下面的set/get/toString使用lombok注解@Getter@Setter@ToStringclassPersonimplementsComparable{privateintid;privateintage;privateStringname;publicPerson(intid,intage,Stringname){this.id=id;this.age=age;this.name=name;}@OverridepublicintcompareTo(Personp){returnp.getAge()-this.getAge();}}以上代码的执行结果如下图所示:核心代码如下:2.使用Comparator进行排序Comparable是类内部的比较方法,Comparator是排序类外部的比较器。使用Comparator不需要修改原来的Person类,只需要扩展Person类的一个Comparator即可。Comparator有两种实现方式:新建一个Comparator;使用Comparator匿名类比较器。其中,第二种实现方式更为简洁。我们通过下面的具体代码来观察一下两者的区别。2.1新建ComparatorpublicclassListSortExample2{publicstaticvoidmain(String[]args){//创建并初始化ListListlist=newArrayList(){{add(newPerson(1,30,"北京"));add(newPerson(2,20,"西安"));add(newPerson(3,40,"上海"));}};//使用Comparator排序Collections.sort(list,newPersonComparator());//打印列表集合list.forEach(p->{System.out.println(p);});}}/***NewPersonComparator*/classPersonComparatorimplementsComparator{@Overridepublicintcompare(Personp1,Personp2){returnp2.getAge()-p1.getAge();}}@Getter@Setter@ToStringclassPerson{privateintid;privateintage;privateStringname;publicPerson(intid,intage,Stringname){this.id=id;this.age=age;this.name=name;}}上述代码的执行结果如下图所示:该方法的核心实现代码如下:2.2匿名类比较器Comparator可以使用更简洁的匿名类来实现排序功能。具体实现代码如下:publicclassListSortExample2{publicstaticvoidmain(String[]args){//创建并初始化ListListlist=newArrayList(){{add(newPerson(1,30,"北京"));添加(新人(2,20,"西安"));add(newPerson(3,40,"上海"));}};//使用匿名比较器排序Collections.sort(list,newComparator(){@Overridepublicintcompare(Personp1,Personp2){returnp2.getAge()-p1.getAge();}});//打印列表集合list.forEach(p->{System.out.println(p);});}}@Getter@Setter@ToStringclassPerson{privateintid;privateintage;privateStringname;publicPerson(intid,intage,Stringname){this.id=id;this.age=age;this.name=name;}}上面代码的执行结果如图下图:3.使用Stream进行排序,JDK8以后可以使用更简单的方法Stream来实现排序功能,其实现只需要一行代码,具体实现如下:publicclassListSortExample3{publicstaticvoidmain(String[]args){//创建并初始化ListListlist=newArrayList(){{add(newPerson(1,30,"北京"));add(newPerson(2,20,"西安"));add(newPerson(3,40,"上海"));}};//使用Stream排序list=list.stream().sorted(Comparator.comparing(Person::getAge).reversed()).collect(Collectors.toList());//打印列表集合list.forEach(p->{System.out.println(p);});}@Getter@Setter@ToStringstaticclassPerson{私有intid;privateintage;privateStringname;publicPerson(intid,intage,Stringname){this.id=id;this.age=age;this.name=name;}}}其中reversed()表示倒序,如果你不使用这个方法正序上述代码的执行结果如下图所示:扩展:当排序字段为null,使用Stream进行排序时,如果排序字段为null值,则会出现异常。具体示例如下:publicclassListSortExample4{publicstaticvoidmain(String[]args){//创建并初始化ListListlist=newArrayList(){{add(newPerson(30,"北京"));add(newPerson(10,"西安"));add(newPerson(40,"上海"));add(newPerson(null,"Shanghai"));//年龄为空值}};//按照[年龄]正序,但年龄中有空值list=list.stream().sorted(Comparator.comparing(Person::getAge)).collect(Collectors.toList());//打印列表集合list.forEach(p->{System.out.println(p);});}}@Getter@Setter@ToStringclassPerson{privateIntegerage;privateStringname;publicPerson(Integerage,Stringname){this.age=age;this.name=name;}}上面代码的执行结果如下图所示:解决上面的问题,需要给Comparator.comparing传递第二个参数:Comparator.nullsXXX,如下代码所示:publicclassListSortExample4{publicstaticvoidmain(String[]args){//创建并初始化ListListlist=newArrayList(){{add(newPerson(30,"北京"));add(newPerson(10,"西安"));add(newPerson(40,"Shanghai"));add(newPerson(null,"Shanghai"));}};//按照[age]正序,但age中有null值list=list.stream().sorted(Comparator.comparing(Person::getAge,Comparator.nullsFirst(Integer::compareTo))).collect(Collectors.toList());//打印列表集合list.forEach(p->{System.out.println(p);});}}@Getter@Setter@ToStringclassPerson{privateIntegerage;privateStringname;publicPerson(Integerage,Stringname){this.age=age;this.name=name;}}Comparator.nullsFirst表示null字段中的值会被排序放在集合的最前面。如果想把null值放在集合的末尾,可以使用上面代码的执行结果Comparator.nullsLast,如下图:总结本文介绍List排序的3种方法,前两种方法常用的在JDK8之前的版本中,比较器Comparator有两种写法,在JDK8之后的版本中,可以使用Comparator.comparing来实现排序。如果排序字段中可能出现空值,使用Comparator.nullsXXX进行排序处理(否则会报错)。