Java Comparator.comparing比較導致空指針異常的解決
Java Comparator.comparing比較導致空指針異常
Comparator.comparing(Department::getOrder)
原因:
public static <T, U extends Comparable<? super U>> Comparator<T> comparing(
Function<? super T, ? extends U> keyExtractor)
{
Objects.requireNonNull(keyExtractor);
return (Comparator<T> & Serializable)
(c1, c2) -> keyExtractor.apply(c1).compareTo(keyExtractor.apply(c2));
}
如果keyExtractor.apply(c1),那么keyExtractor.apply(c1).compareTo(XX)將報空指針異常
替代方案
Comparator.comparing(Department::getOrder, Comparator.nullsFirst(Comparator.naturalOrder()))
替代方案好處:
public static <T, U> Comparator<T> comparing(
Function<? super T, ? extends U> keyExtractor,
Comparator<? super U> keyComparator)
{
Objects.requireNonNull(keyExtractor);
Objects.requireNonNull(keyComparator);
return (Comparator<T> & Serializable)
(c1, c2) -> keyComparator.compare(keyExtractor.apply(c1),
keyExtractor.apply(c2));
}
會先取出keyExtractor.apply(c1)和keyExtractor.apply(c2),放入比較器進行比較
而Comparator.nullsFirst作為比較器,會創(chuàng)建一個Comparators.NullComparator比較器
public static <T> Comparator<T> nullsFirst(Comparator<? super T> comparator) {
return new Comparators.NullComparator<>(true, comparator);
}
Comparators.NullComparator比較器的compare接口實現(xiàn)中先進行空值判斷處理,不為空的再進行代入比較器比較
/**
* Null-friendly comparators
*/
final static class NullComparator<T> implements Comparator<T>, Serializable {
private static final long serialVersionUID = -7569533591570686392L;
private final boolean nullFirst;
// if null, non-null Ts are considered equal
private final Comparator<T> real;
@SuppressWarnings("unchecked")
NullComparator(boolean nullFirst, Comparator<? super T> real) {
this.nullFirst = nullFirst;
this.real = (Comparator<T>) real;
}
@Override
public int compare(T a, T b) {
if (a == null) {
return (b == null) ? 0 : (nullFirst ? -1 : 1);
} else if (b == null) {
return nullFirst ? 1: -1;
} else {
return (real == null) ? 0 : real.compare(a, b);
}
}
@Override
public Comparator<T> thenComparing(Comparator<? super T> other) {
Objects.requireNonNull(other);
return new NullComparator<>(nullFirst, real == null ? other : real.thenComparing(other));
}
@Override
public Comparator<T> reversed() {
return new NullComparator<>(!nullFirst, real == null ? null : real.reversed());
}
}
Comparator中comparing方法的學習
例子:
我們需要根據(jù)對象中的name字段進行不規(guī)則排序
排序規(guī)則為(PPD > 政府 > 合作)
public class Obj {
private String name;
private BigDecimal price;
......
}
@Test
public void sort() {
List<Obj> list = Arrays.asList(
new Obj("政府", null),
new Obj("政府", new BigDecimal("1216.23")),
new Obj("商業(yè)", new BigDecimal("123.23")),
new Obj("PPD", new BigDecimal("123.23")),
new Obj("合作", new BigDecimal("127.23")),
new Obj(null, new BigDecimal("125.23")));
List<String> sortList = Arrays.asList("PPD","政府","合作");
List<Obj> result = list.stream().sorted(
//先按照name排序(模擬需求的a屬性排序)
Comparator.comparing(Obj::getName,(x,y)-> {
if(x == null && y != null){
return 1;
}else if(x !=null && y == null){
return -1;
}else if(x == null && y == null){
return -1;
} else {
for(String sort : sortList){
if(sort.equals(x) || sort.equals(y)){
if(x.equals(y)){
return 0;
}else if(sort.equals(x)){
return -1;
}else{
return 1;
}
}
}
return 0;
}
})).collect(Collectors.toList());
System.out.println(result);
}
1.實現(xiàn)
comparing方法有兩種實現(xiàn)
方法1:只有一個參數(shù),參數(shù)的類型是一個函數(shù)式接口 
方法2:
問:這個方法中泛型是怎么傳遞的
1、list.stream()時,獲取的stream流已經(jīng)確定了泛型了,此時返回的對象為Stream<Obj>
2、Stream對象的sorted方法,需要比較器的類型需要是Obj.calss或者是Obj的父類

3、而我們這邊調(diào)用了靜態(tài)方法Comparator.comparing,靜態(tài)方法中的泛型是根據(jù)傳的參數(shù)中的類型來決定的

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
面向?qū)ο蠛兔嫦蜻^程的區(qū)別(動力節(jié)點java學院整理)
很多朋友不清楚面向?qū)ο蠛兔嫦蜻^程有什么區(qū)別,接下來小編給大家整理了關于面向?qū)ο蠛兔嫦蜻^程的區(qū)別講解,感興趣的朋友可以參考下2017-04-04
idea插件之如何使用JarEditor編輯Java JAR文件
JarEditor是一款用于在IntelliJIDEA中直接編輯JAR文件的插件,支持反編譯查看和編輯.class文件,并提供即時編譯與保存功能,通過JarEditor,用戶可以在IDE內(nèi)一站式完成JAR文件的編輯、管理和打包操作,提高開發(fā)效率,但在生產(chǎn)環(huán)境中使用前,請確保備份并測試修改2025-01-01

