天天看點

java-jdk8特性Lamda表達式、增強版Comparator進行集合排序

作者:瓦下枯草
java-jdk8特性Lamda表達式、增強版Comparator進行集合排序

jdk8特性Lamda表達式、增強版Comparator進行集合排序

工作場景遇見得異常如下:

Exception in thread "main" java.lang.NullPointerException
at java.util.Comparator.lambda$comparing$77a9974f$1(Comparator.java:469)
at java.util.Comparator.lambda$thenComparing$36697e65$1(Comparator.java:216)
at java.util.Comparator.lambda$thenComparing$36697e65$1(Comparator.java:216)
at java.util.Comparator.lambda$thenComparing$36697e65$1(Comparator.java:216)
at java.util.TimSort.countRunAndMakeAscending(TimSort.java:360)
at java.util.TimSort.sort(TimSort.java:220)
at java.util.Arrays.sort(Arrays.java:1512)
at java.util.ArrayList.sort(ArrayList.java:1464)
at com.example.commonbase.listutils.ListSortTest2.main(ListSortTest2.java:16)           
問題代碼,簡化如下(這裡貼出的是示例)
@Data
public class Student {
private String no;
private String name;
private Integer age;
private BigDecimal money;
}
// List排序
public static void main(String[] args) {
List<Student> dataList = ListSortTest2.initData();
dataList.sort(Comparator.comparing(Student::getNo)
.thenComparing(Student::getAge)
.thenComparing(Student::getName).thenComparing(Student::getMoney));
System.out.println("結果時:" + JSONObject.toJSONString(dataList));
}
public static List<Student> initData() {
List<Student> result = new ArrayList<>();
for(int i=0; i< 10; i++) {
Student element = new Student();
element.setNo("no" + i);
element.setName("name" + i);
element.setAge(i);
element.setMoney(new BigDecimal(i));
result.add(element);
}
{
// 這裡特别新增了一個:未指派no,money
Student element = new Student();
element.setName("name");
element.setAge(100);
result.add(element);
}
return result;
}           

為了解決上述問題,點選進下Comparator的源碼

java-jdk8特性Lamda表達式、增強版Comparator進行集合排序

裡面很多調用了方法Objects.requireNonNull(?)

這就要求比對的對象和字段,不可為空。為空時會報上述遇見的異常。

繼續跟進Comparator的源碼
/**
* Returns a null-friendly comparator that considers {@code null} to be
* less than non-null. When both are {@code null}, they are considered
* equal. If both are non-null, the specified {@code Comparator} is used
* to determine the order. If the specified comparator is {@code null},
* then the returned comparator considers all non-null values to be equal.
*
* <p>The returned comparator is serializable if the specified comparator
* is serializable.
*
* @param <T> the type of the elements to be compared
* @param comparator a {@code Comparator} for comparing non-null values
* @return a comparator that considers {@code null} to be less than
* non-null, and compares non-null objects with the supplied
* {@code Comparator}.
* @since 1.8
*/
public static <T> Comparator<T> nullsFirst(Comparator<? super T> comparator) {
return new Comparators.NullComparator<>(true, comparator);
}
/**
* Returns a null-friendly comparator that considers {@code null} to be
* greater than non-null. When both are {@code null}, they are considered
* equal. If both are non-null, the specified {@code Comparator} is used
* to determine the order. If the specified comparator is {@code null},
* then the returned comparator considers all non-null values to be equal.
*
* <p>The returned comparator is serializable if the specified comparator
* is serializable.
*
* @param <T> the type of the elements to be compared
* @param comparator a {@code Comparator} for comparing non-null values
* @return a comparator that considers {@code null} to be greater than
* non-null, and compares non-null objects with the supplied
* {@code Comparator}.
* @since 1.8
*/
public static <T> Comparator<T> nullsLast(Comparator<? super T> comparator) {
return new Comparators.NullComparator<>(false, comparator);
}           

nullsFirst和nullsLast 兩個方法。分别是處理null的場景(放在前面/放在後面)。

源碼可以看到很多注解:since 1.8 這是1.8版本開始有的新特性哦~

修改之後的代碼如下:

dataList.sort(Comparator.comparing(Student::getNo, 
                                   Comparator.nullsFirst(String::compareTo).reversed())
  											.thenComparing(Student::getAge)
												.thenComparing(Student::getName)
  											.thenComparing(Student::getMoney));           
java-jdk8特性Lamda表達式、增強版Comparator進行集合排序