Как игнорировать нулевые значения в Comparator? - PullRequest
0 голосов
/ 05 июля 2018

У меня есть компаратор, который сравнивает вложенные поля объекта. Здесь price из product.

Проблема: если поле пустое, я получаю исключение NullPointerException.

Вопрос: как я могу сказать компаратору игнорировать объекты, у которых поле сравнения равно нулю, без (!) Предварительной фильтрации списка? Под игнорированием я имею в виду, что они находятся в конце списка.

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

Результат:

java.lang.NullPointerException
    at java.util.Comparator.lambda$comparing$77a9974f$1(Comparator.java:469)
    at java.util.TimSort.binarySort(TimSort.java:296)
    at java.util.TimSort.sort(TimSort.java:221)
    at java.util.Arrays.sort(Arrays.java:1438)
    at java.util.Arrays$ArrayList.sort(Arrays.java:3895)
    at java.util.Collections.sort(Collections.java:175)

Ответы [ 3 ]

0 голосов
/ 05 июля 2018

Вы получаете исключение 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;
    }
}
0 голосов
/ 07 июля 2019

Вы можете использовать Optional <>, чтобы увидеть, является ли результат от getter нулевым или допустимым значением. Для нулевых значений вы можете поместить их в хвост или голову, всегда обрабатывая их результат сравнения () равен -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;
        }
        ...
}
0 голосов
/ 05 июля 2018

Вы можете использовать метод nullsLast Компаратора:

   private static final Comparator PRODUCT_COMPARATOR = 
           Comparator
           .nullsLast(Comparator.comparing(p -> p.details.price, Comparator.nullsLast(Comparator.naturalOrder())));

Первое значение nullLast для продукта равно нулю, второе - цене 0.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...