我有一个比较器,用于比较对象的嵌套字段。这里是price
的{{1}}。
问题:如果该字段为null,则显示NullPointerException。
问题:如何让比较器忽略比较字段为null的对象,而无需(!)事先过滤列表? “忽略”是指将它们放在列表的末尾。
product
结果:
public class SorterTest {
private static final Comparator<Product> PRODUCT_COMPARATOR =
Comparator.comparing(p -> p.details.price);
static class Product {
String name;
Details details;
static class Details {
BigDecimal price;
}
}
@Test
public void test() {
List<Product> products = Arrays.asList(
createProduct("A", new BigDecimal(30.00)),
createProduct("B", new BigDecimal(55.00)),
createProduct("C", new BigDecimal(20.00)),
createProduct("D", null),
createProduct("E", null),
createProduct("F", null)
);
Collections.sort(products, PRODUCT_COMPARATOR);
assertEquals("C", products.get(0).name);
assertEquals("A", products.get(1).name);
assertEquals("B", products.get(2).name);
assertEquals("D", products.get(3).name);
assertEquals("E", products.get(4).name);
assertEquals("F", products.get(5).name);
}
private Product createProduct(String name, BigDecimal price) {
Product p = new Product();
p.details = new Product.Details();
p.name = name;
p.details.price = price;
return p;
}
}
答案 0 :(得分:3)
您可以使用Comparator的nullsLast方法:
private static final Comparator PRODUCT_COMPARATOR = Comparator .nullsLast(Comparator.comparing(p -> p.details.price, Comparator.nullsLast(Comparator.naturalOrder())));
Product的第一个null持续时间为null,价格的第二个null为空。
答案 1 :(得分:0)
由于价格为null,因此您将收到NullPointerException。因此,使用if语句检查价格值,如果为null,则使用其他值(如0)替换价格。代码可能像:
public class SorterTest {
private static final Comparator<Product> PRODUCT_COMPARATOR =
Comparator.comparing(p->
{
if (p.details != null && p.details.price != null) {
return p.details.price;
} else {
return new BigDecimal(0);
}
}
);
static class Product {
String name;
Details details;
static class Details {
BigDecimal price;
}
}
@Test
public void test() {
List<Product> products = Arrays.asList(
createProduct("A", new BigDecimal(30.00)),
createProduct("B", new BigDecimal(55.00)),
createProduct("C", new BigDecimal(20.00)),
createProduct("D", null),
createProduct("E", null),
createProduct("F", null)
);
Collections.sort(products, PRODUCT_COMPARATOR);
assertEquals("D", products.get(0).name);
assertEquals("E", products.get(1).name);
assertEquals("F", products.get(2).name);
assertEquals("C", products.get(3).name);
assertEquals("A", products.get(4).name);
assertEquals("B", products.get(5).name);
}
private Product createProduct(String name, BigDecimal price) {
Product p = new Product();
p.details = new Product.Details();
p.name = name;
p.details.price = price;
return p;
}
}
答案 2 :(得分:0)
您可以使用Optional <>来查看getter的结果是否为null或有效值。对于空值,可以通过始终将其comparer()结果设为-1或1来将它们放在尾部或头部。
private static final Comparator<Product> PRODUCT_COMPARATOR =
Comparator.comparing(p -> {
Optional<BigDecimal> res = Optional.ofNullable(p.getPrice);
if(res.isPresent())
return p.getPrice();
else
return -1;
});
...
static class Product {
String name;
BigDecimal price;
BigDecimal getPrice(){
return this.price;
}
...
}