使用默认实现的 null 安全映射比较器

null-safe mapping Comparator using default implementations

提问人:flo 提问时间:2/13/2015 更新时间:4/9/2023 访问量:32501

问:

是否有内置的可能性可以在 Java 8 中创建 null 安全映射比较器而无需编写自己的实现?Comparator

运行以下代码时,它会导致 NPE,因为 的参数可能会返回一个值:keyExtractorComparator.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$comparing$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) 在测试中。ToSort.main(ToSort.java:48)

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

也不起作用,因为只有正确踩踏的对象。ToSortnull

我知道如何编写自己的实现,我只是在寻找一个更“优雅”的解决方案,比如Comparator

Comparator.comparingNullsFirst(ToSort::getSortBy)
Java-8 比较器

评论


答:

208赞 flo 2/13/2015 #1

找到了一个可能的解决方案:

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

评论

3赞 Geert 9/29/2020
因此,此解决方案之所以有效,是因为比较器的嵌套顺序。在你的问题中,最里面的比较器(因此是第一个被执行的)是,并且被包裹在它周围。在此答案中,比较器现在首先执行,在返回空值的调用之前提供安全性ToSort::getSortBynullsFirstnullsFirstgetSortBy
1赞 cody.tv.weber 4/5/2023 #2

流代码段:

somePersonList
    .stream()
    .sorted(
        Comparator.comparing(SomePerson::getName,
        Comparator.nullsLast(String::compareTo))
    )
    .collect(Collectors.toList())