Порівнювач нульових параметрів зіставлення за допомогою стандартних реалізацій


82

Чи існує вбудована можливість створити нульовий безпечний порівняльник зіставлення в Java 8 без написання власної реалізації Comparator?

При запуску наступного коду він викликає NPE, оскільки keyExtractorаргумент Comparator.comparing()може повертати nullзначення:

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

    }
}

Виняток у потоці "main" java.lang.NullPointerException у java.util.Comparator.lambda $ порівняння $ 77a9974f $ 1 (Comparator.java:469) у java.util.Comparator $$ Lambda $ 2 / 1480010240.compare (Невідоме джерело) на java.util.Comparators $ NullComparator.compare (Comparators.java:83) на java.util.TreeMap.getEntryUsingComparator (TreeMap.java:376) на java.util.TreeMap.getEntry (TreeMap.java:345) на java.util .TreeMap.containsKey (TreeMap.java:232) на java.util.TreeSet.contains (TreeSet.java:234) у test.ToSort.main (ToSort.java:48)

Використовуючи

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

також не працює, оскільки лише ToSortоб’єкти, які nullправильно протаптані.

Я знаю, як писати власну Comparatorреалізацію, я просто шукаю більш "елегантне" рішення

Comparator.comparingNullsFirst(ToSort::getSortBy)

Відповіді:


138

Знайдено можливе рішення:

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

Отже, причина, по якій це рішення працює, полягає в порядку вкладеності компараторів. У вашому запитанні був найпотаємніший порівняльник (і, отже, перший виконаний), ToSort::getSortByі nullsFirstйого обернули навколо. У цій відповіді nullsFirstпорівняльник тепер виконується першим, забезпечуючи безпеку перед нульовими зворотними getSortByдзвінками
Гірт,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.