null-safe mapping使用默认实现的Comparator

flo*_*flo 62 java comparator java-8

是否有内置的可能性在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

    }
}
Run Code Online (Sandbox Code Playgroud)

java.util.Comparator.lambda中线程"main"java.lang.NullPointerException中的异常$比较java.util.Comparator上的$ 77a9974f $ 1(Comparator.java:469)$$ Lambda $ 2/1480010240.compare(未知来源)at java.util.Comparators $ NullComparator.compare(Comparators.java:83),java.util.TreeMap.getEntryUsingComparator(TreeMap.java:376),位于java.util的java.util.TreeMap.getEntry(TreeMap.java:345) .TreeMap.containsKey(TreeMap.java:232)at java.util.TreeSet.contains(TreeSet.java:234)at test.ToSort.main(ToSort.java:48)

运用

Comparator<ToSort> comp = Comparator.nullsFirst(Comparator.comparing(ToSort::getSortBy));
Run Code Online (Sandbox Code Playgroud)

不起作用,因为只有正确处理的ToSort对象null.

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

Comparator.comparingNullsFirst(ToSort::getSortBy)
Run Code Online (Sandbox Code Playgroud)

flo*_*flo 108

找到可能的解决方案:

Comparator.comparing(ToSort::getSortBy, 
      Comparator.nullsFirst(Comparator.naturalOrder())
)
Run Code Online (Sandbox Code Playgroud)

  • 因此,该解决方案之所以有效,是因为比较器的嵌套顺序。在您的问题中,最里面的比较器(因此第一个要执行的比较器)是“ToSort::getSortBy”,并且“nullsFirst”包裹在它周围。在这个答案中,现在首先执行“nullsFirst”比较器,在返回 null 的“getSortBy”调用之前提供安全性 (3认同)