Null-Safe-Mapping-Komparator mit Standardimplementierungen


76

Gibt es eine integrierte Möglichkeit, einen nullsicheren Mapping-Komparator in Java 8 zu erstellen, ohne eine eigene Implementierung von zu schreiben Comparator?

Wenn der folgende Code ausgeführt wird, wird eine NPE verursacht, da das keyExtractorArgument von Comparator.comparing()möglicherweise einen nullWert zurückgibt:

public class ToSort
{

    private String sortBy;

    public ToSort(String sortBy)
    {
        this.sortBy = sortBy;
    }

    public String getSortBy()
    {
        return sortBy;
    }

    public static void main(String[] args)
    {
        // mapping comparator
        Comparator<ToSort> comp = Comparator.comparing(ToSort::getSortBy);                          
        SortedSet<ToSort> set = new TreeSet<>(comp);
        ToSort o1 = new ToSort("1");
        ToSort o2 = new ToSort(null);

        set.add(o1);

        System.out.println(set.contains(o2)); //NPE because o2.getSortBy() == null

    }
}

Ausnahme im Thread "main" java.lang.NullPointerException bei java.util.Comparator.lambda $ im Vergleich von $ 77a9974f $ 1 (Comparator.java:469) bei java.util.Comparator $$ Lambda $ 2 / 1480010240.compare (Unbekannte Quelle) bei java.util.Comparators $ NullComparator.compare (Comparators.java:83) bei java.util.TreeMap.getEntryUsingComparator (TreeMap.java:376) bei java.util.TreeMap.getEntry (TreeMap.java:345) bei java.util .TreeMap.containsKey (TreeMap.java:232) unter java.util.TreeSet.contains (TreeSet.java:234) unter test.ToSort.main (ToSort.java:48)

Verwenden von

Comparator<ToSort> comp = Comparator.nullsFirst(Comparator.comparing(ToSort::getSortBy));

funktioniert auch nicht, da nur ToSortObjekte nullrichtig betreten werden.

Ich weiß, wie man meine eigene ComparatorImplementierung schreibt, ich suche nur nach einer "eleganteren" Lösung wie

Comparator.comparingNullsFirst(ToSort::getSortBy)

Antworten:


132

Eine mögliche Lösung gefunden:

Comparator.comparing(ToSort::getSortBy, 
      Comparator.nullsFirst(Comparator.naturalOrder())
)

Der Grund, warum diese Lösung funktioniert, liegt in der Reihenfolge der Verschachtelung der Komparatoren. In Ihrer Frage war der innerste Komparator (und damit der erste, der ausgeführt wurde) ToSort::getSortByund der nullsFirstwurde darum gewickelt. In dieser Antwort das nullsFirstist Komparator nun zuerst ausgeführt und bietet Sicherheit vor den Null-Rückkehr getSortByAnrufe
Geert
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.