Java Comparator.comparing比較導(dǎo)致空指針異常的解決
Java Comparator.comparing比較導(dǎo)致空指針異常
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)將報(bào)空指針異常
替代方案
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)); }
會(huì)先取出keyExtractor.apply(c1)和keyExtractor.apply(c2),放入比較器進(jìn)行比較
而Comparator.nullsFirst作為比較器,會(huì)創(chuàng)建一個(gè)Comparators.NullComparator比較器
public static <T> Comparator<T> nullsFirst(Comparator<? super T> comparator) { return new Comparators.NullComparator<>(true, comparator); }
Comparators.NullComparator比較器的compare接口實(shí)現(xiàn)中先進(jìn)行空值判斷處理,不為空的再進(jì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方法的學(xué)習(xí)
例子:
我們需要根據(jù)對(duì)象中的name字段進(jìn)行不規(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.實(shí)現(xiàn)
comparing方法有兩種實(shí)現(xiàn)
方法1:只有一個(gè)參數(shù),參數(shù)的類型是一個(gè)函數(shù)式接口
方法2:
問(wèn):這個(gè)方法中泛型是怎么傳遞的
1、list.stream()時(shí),獲取的stream流已經(jīng)確定了泛型了,此時(shí)返回的對(duì)象為Stream<Obj>
2、Stream對(duì)象的sorted方法,需要比較器的類型需要是Obj.calss或者是Obj的父類
3、而我們這邊調(diào)用了靜態(tài)方法Comparator.comparing,靜態(tài)方法中的泛型是根據(jù)傳的參數(shù)中的類型來(lái)決定的
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Java中關(guān)于int和Integer的區(qū)別詳解
本篇文章小編為大家介紹,在Java中 關(guān)于int和Integer的區(qū)別詳解,需要的朋友參考下2013-04-04Mybatis查詢返回兩個(gè)或多個(gè)參數(shù)問(wèn)題
這篇文章主要介紹了Mybatis查詢返回兩個(gè)或多個(gè)參數(shù)問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-06-06淺談Java中Spring Boot的優(yōu)勢(shì)
在本篇文章中小編給大家分析了Java中Spring Boot的優(yōu)勢(shì)以及相關(guān)知識(shí)點(diǎn)內(nèi)容,興趣的朋友們可以學(xué)習(xí)參考下。2018-09-09面向?qū)ο蠛兔嫦蜻^(guò)程的區(qū)別(動(dòng)力節(jié)點(diǎn)java學(xué)院整理)
很多朋友不清楚面向?qū)ο蠛兔嫦蜻^(guò)程有什么區(qū)別,接下來(lái)小編給大家整理了關(guān)于面向?qū)ο蠛兔嫦蜻^(guò)程的區(qū)別講解,感興趣的朋友可以參考下2017-04-04idea插件之如何使用JarEditor編輯Java JAR文件
JarEditor是一款用于在IntelliJIDEA中直接編輯JAR文件的插件,支持反編譯查看和編輯.class文件,并提供即時(shí)編譯與保存功能,通過(guò)JarEditor,用戶可以在IDE內(nèi)一站式完成JAR文件的編輯、管理和打包操作,提高開(kāi)發(fā)效率,但在生產(chǎn)環(huán)境中使用前,請(qǐng)確保備份并測(cè)試修改2025-01-01java文件的簡(jiǎn)單讀寫(xiě)操作方法實(shí)例分析
這篇文章主要介紹了java文件的簡(jiǎn)單讀寫(xiě)操作方法,結(jié)合實(shí)例形式分析了java文件流進(jìn)行讀寫(xiě)操作的方法與相關(guān)操作注意事項(xiàng),需要的朋友可以參考下2020-05-05