Java8 空安全比较
Java8 Null-safe comparison
比较两种产品时遇到问题。我想比较它们每个的年份(可选)属性。但是只要此属性为 null,就会抛出 NPE。我想 Comparator.nullsLast(..) 我可以处理空值...但似乎我对它的工作原理有误解,或者代码有问题。我需要更改什么才能使这项工作对 null 友好?
@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());
}
提前致谢
应该是
Comparator<IShopProduct> comparator =
Comparator.comparing( IShopProduct::getVintage,
Comparator.nullLast(naturalOrder()));
Comparator.nullFirst()/nullLast()
将空值视为 greater/smaller 而不是非空对象
编辑
这是 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
。
这些值将传递给解析为 value1.compareTo(value2)
的 naturalOrder()
比较器。通常它会抛出 NPE 但我们用 Comparator.nullLast
包装了它,它有特殊的 null
处理程序。
如果传入的键提取函数是 null
或提取的 属性 是 null
,comparing 方法的重载将抛出异常。因为,您提到 vintage
属性 有时可以是 null
那么这就是 NullPointerException 的原因。
另一种解决问题的方法是使用这个比较器:
Comparator<IShopProduct> comparator =
Comparator.comparing(IShopProduct::getVintage,
Comparator.nullsLast(naturalOrder()));
键提取器即 IShopProduct::getVintage
是用于提取排序键的函数。
键比较器即Comparator.nullsLast(Comparator.naturalOrder())
用于比较排序键。
Comparator.naturalOrder()
这里只是 returns 一个按自然顺序比较 Comparable
对象的比较器。
比较两种产品时遇到问题。我想比较它们每个的年份(可选)属性。但是只要此属性为 null,就会抛出 NPE。我想 Comparator.nullsLast(..) 我可以处理空值...但似乎我对它的工作原理有误解,或者代码有问题。我需要更改什么才能使这项工作对 null 友好?
@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());
}
提前致谢
应该是
Comparator<IShopProduct> comparator =
Comparator.comparing( IShopProduct::getVintage,
Comparator.nullLast(naturalOrder()));
Comparator.nullFirst()/nullLast()
将空值视为 greater/smaller 而不是非空对象
编辑
这是 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
我建议使用以下函数的代码:
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
。
这些值将传递给解析为 value1.compareTo(value2)
的 naturalOrder()
比较器。通常它会抛出 NPE 但我们用 Comparator.nullLast
包装了它,它有特殊的 null
处理程序。
如果传入的键提取函数是 null
或提取的 属性 是 null
,comparing 方法的重载将抛出异常。因为,您提到 vintage
属性 有时可以是 null
那么这就是 NullPointerException 的原因。
另一种解决问题的方法是使用这个比较器:
Comparator<IShopProduct> comparator =
Comparator.comparing(IShopProduct::getVintage,
Comparator.nullsLast(naturalOrder()));
键提取器即 IShopProduct::getVintage
是用于提取排序键的函数。
键比较器即Comparator.nullsLast(Comparator.naturalOrder())
用于比较排序键。
Comparator.naturalOrder()
这里只是 returns 一个按自然顺序比较 Comparable
对象的比较器。