Java8 Null安全比较

时间:2018-05-07 13:24:04

标签: java comparator comparable

比较两种产品时遇到问题。我希望比较每个人的年份(可选)属性。但只要此属性为null,就会抛出NPE。我想用Comparator.nullsLast(..)我可以处理空值...但似乎我对这是如何工作或者代码有问题有误解。我需要更改什么来使这项工作无效?

@Override
public int compare(IProduct product1, IProduct product2) throws ProductComparisonException {

    Comparator<IShopProduct> comparator =
        Comparator.nullsLast(Comparator.comparing(IShopProduct::getVintage));

    return comparator.compare((IShopProduct)product1.getProvidedProductData(),
                              (IShopProduct)product2.getProvidedProductData());
}

提前致谢

2 个答案:

答案 0 :(得分:2)

如果传入的密钥提取器函数为null或提取的属性为null,则comparing方法的此重载将引发异常。既然如此,你提到vintage属性有时可能是null,那么这就是Nul​​lPointerException的原因。

另一种解决方法是使用这种比较器:

 Comparator<IShopProduct> comparator = 
      Comparator.comparing(IShopProduct::getVintage,
                Comparator.nullsLast(naturalOrder()));

密钥提取器,即IShopProduct::getVintage是用于提取排序键的函数。

密钥比较器,即Comparator.nullsLast(Comparator.naturalOrder())用于比较排序密钥。

Comparator.naturalOrder()这里只返回一个比较器,按自然顺序比较Comparable个对象。

答案 1 :(得分:0)

应该是

Comparator<IShopProduct> comparator = 
            Comparator.comparing( IShopProduct::getVintage, 
                             Comparator.nullLast(naturalOrder()));

Comparator.nullFirst()/nullLast()认为空值大于/小于nonNull对象

修改

这是Comparator.comparing()的实现:

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).compareTo(),因此如果keyExtractor.apply(c1)null

,它会抛出NPE

我建议的代码使用以下函数:

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));
}

基本上它会提取值,然后将比较值传递给Comparator

这些值将传递给naturalOrder()比较器,该比较器已解析为value1.compareTo(value2)。通常它会抛出NPE,但是我们用Comparator.nullLast包装它,它有特殊的null处理程序。