比较器:比较 2 个对象与可以为空的字段
Comparator: Comparing 2 objects with field which can be null
我需要通过实现默认比较器的典型比较方法来编写 Comparator
。这是由于我需要实现的接口。
我的对象是具有 Integer
字段 vintage
的产品,可以是 null
。代码如下:
@Override
public int compare ( IProduct product1, IProduct product2 ) throws ProductComparisonException
{
if ( product1 == null && product2 == null )
{
return 0;
}
else if ( product1 == null && product2 != null )
{
return -1;
}
else if ( product1 != null && product2 == null )
{
return 1;
}
IProductData productData1 = (IProductData ) product1.getProvidedProductData();
IProductData productData2 = (IProductData ) product2.getProvidedProductData();
if ( productData1.getVintage() == null && productData2.getVintage() == null )
{
return 0;
}
else if ( productData1.getVintage() == null && productData2.getVintage() != null )
{
return -1;
}
else if ( productData1.getVintage() != null && productData2.getVintage() == null )
{
return 1;
}
return productData2.getVintage().compareTo( productData2.getVintage() );
}
我对此不满意,因为我有很多重复的代码,而且我确信有更好的方法来做到这一点...任何建议都将不胜感激。
简单使用(我假设你在 Java8+ 因为你用 lambda
标记了问题)
来自 Comparator 的以下任一方法:
public static <T> Comparator<T> nullsFirst(Comparator<? super T> comparator)
public static <T> Comparator<T> nullsLast(Comparator<? super T> comparator)
一种可能性是泛化 null 检查。
public int compare(IProduct product1, IProduct product2) throws ProductComparisonException {
Integer diff = nullCompare(product1, product2);
if(diff != null) return diff;
IProductData productData1 = (IProductData)product1.getProvidedProductData();
IProductData productData2 = (IProductData)product2.getProvidedProductData();
diff = nullCompare(productData1.getVintage(), productData2.getVintage());
if(diff != null) return diff;
return productData2.getVintage().compareTo(productData2.getVintage());
}
// Using Integer so I can return `null`.
private Integer nullCompare(Object o1, Object o2) {
if (o1 == null && o2 == null) {
return 0;
}
else if (o1 == null && o2 != null) {
return -1;
}
else if (o1 != null && o2 == null) {
return 1;
}
return null;
}
您可以使用 Comparator
中介绍的方法 Java 8 并使用方法参考,例如:
Comparator.comparing(IProductData::getVintage, Comparator.nullsLast(Comparator.naturalOrder()))
将您的 Comparator
包裹在 Comparator.nullsFirst
中以避免处理可能 null
可用的参数。
您需要两个 Comparator
与 Comparator#thenComparing
合并:
nullsFirst(naturalOrder())
先比较IProduct
;
nullsFirst(comparing(p -> p...getVintage())
再比较他们的 Vintage
。
Comparator<IProduct> comparator =
nullsFirst(Comparator.<IProduct>naturalOrder())
.thenComparing(nullsFirst(
comparing(p -> p.getProvidedProductData().getVintage())
)
);
这种方法比较 IProduct
很自然,您显然不想这样做。 (你根本没有比较它们)。
然后你可以写 IProduct p1, IProduct p2) -> 0
在两个 IProduct
都不是 null
之后继续比较 Vintage
s。
Comparator<IProduct> comparator =
nullsFirst((IProduct p1, IProduct p2) -> 0)
.thenComparing(nullsFirst(
comparing(p -> p.getProvidedProductData().getVintage())
)
);
如果 getVintage
returns 和 int
,您可以使用 Comparator.comparingInt
而不是 Comparator.comparing
:
comparingInt(p -> p.getProvidedProductData().getVintage())
这个怎么样?:
Comparator<IProduct> comparator = (p1, p2) -> {
Integer v1 = p1 != null ? p1.getProvidedProductData() : null;
Integer v2 = p2 != null ? p2.getProvidedProductData() : null;
if (v1 == null ^ v2 == null)
return v1 != null ? 1 : -1;
return v1 != null ? v1.compareTo(v2) : 0;
};
我需要通过实现默认比较器的典型比较方法来编写 Comparator
。这是由于我需要实现的接口。
我的对象是具有 Integer
字段 vintage
的产品,可以是 null
。代码如下:
@Override
public int compare ( IProduct product1, IProduct product2 ) throws ProductComparisonException
{
if ( product1 == null && product2 == null )
{
return 0;
}
else if ( product1 == null && product2 != null )
{
return -1;
}
else if ( product1 != null && product2 == null )
{
return 1;
}
IProductData productData1 = (IProductData ) product1.getProvidedProductData();
IProductData productData2 = (IProductData ) product2.getProvidedProductData();
if ( productData1.getVintage() == null && productData2.getVintage() == null )
{
return 0;
}
else if ( productData1.getVintage() == null && productData2.getVintage() != null )
{
return -1;
}
else if ( productData1.getVintage() != null && productData2.getVintage() == null )
{
return 1;
}
return productData2.getVintage().compareTo( productData2.getVintage() );
}
我对此不满意,因为我有很多重复的代码,而且我确信有更好的方法来做到这一点...任何建议都将不胜感激。
简单使用(我假设你在 Java8+ 因为你用 lambda
标记了问题)
来自 Comparator 的以下任一方法:
public static <T> Comparator<T> nullsFirst(Comparator<? super T> comparator)
public static <T> Comparator<T> nullsLast(Comparator<? super T> comparator)
一种可能性是泛化 null 检查。
public int compare(IProduct product1, IProduct product2) throws ProductComparisonException {
Integer diff = nullCompare(product1, product2);
if(diff != null) return diff;
IProductData productData1 = (IProductData)product1.getProvidedProductData();
IProductData productData2 = (IProductData)product2.getProvidedProductData();
diff = nullCompare(productData1.getVintage(), productData2.getVintage());
if(diff != null) return diff;
return productData2.getVintage().compareTo(productData2.getVintage());
}
// Using Integer so I can return `null`.
private Integer nullCompare(Object o1, Object o2) {
if (o1 == null && o2 == null) {
return 0;
}
else if (o1 == null && o2 != null) {
return -1;
}
else if (o1 != null && o2 == null) {
return 1;
}
return null;
}
您可以使用 Comparator
中介绍的方法 Java 8 并使用方法参考,例如:
Comparator.comparing(IProductData::getVintage, Comparator.nullsLast(Comparator.naturalOrder()))
将您的 Comparator
包裹在 Comparator.nullsFirst
中以避免处理可能 null
可用的参数。
您需要两个 Comparator
与 Comparator#thenComparing
合并:
nullsFirst(naturalOrder())
先比较IProduct
;nullsFirst(comparing(p -> p...getVintage())
再比较他们的Vintage
。Comparator<IProduct> comparator = nullsFirst(Comparator.<IProduct>naturalOrder()) .thenComparing(nullsFirst( comparing(p -> p.getProvidedProductData().getVintage()) ) );
这种方法比较 IProduct
很自然,您显然不想这样做。 (你根本没有比较它们)。
然后你可以写 IProduct p1, IProduct p2) -> 0
在两个 IProduct
都不是 null
之后继续比较 Vintage
s。
Comparator<IProduct> comparator =
nullsFirst((IProduct p1, IProduct p2) -> 0)
.thenComparing(nullsFirst(
comparing(p -> p.getProvidedProductData().getVintage())
)
);
如果 getVintage
returns 和 int
,您可以使用 Comparator.comparingInt
而不是 Comparator.comparing
:
comparingInt(p -> p.getProvidedProductData().getVintage())
这个怎么样?:
Comparator<IProduct> comparator = (p1, p2) -> {
Integer v1 = p1 != null ? p1.getProvidedProductData() : null;
Integer v2 = p2 != null ? p2.getProvidedProductData() : null;
if (v1 == null ^ v2 == null)
return v1 != null ? 1 : -1;
return v1 != null ? v1.compareTo(v2) : 0;
};