Java8 нулевое безопасное сравнение - PullRequest
0 голосов
/ 07 мая 2018

Проблемы со сравнением двух продуктов. Я хочу сравнить винтажный (который не является обязательным) атрибут каждого из них. Но всякий раз, когда этот атрибут имеет значение 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 голосов
/ 07 мая 2018

Эта перегрузка сравнивающего метода вызовет исключение, если переданная в функцию извлечения ключа равна null или извлеченное свойство равно null. Так как вы упомянули, что свойство vintage может время от времени быть null, то это является причиной исключения NullPointerException.

Альтернативой для преодоления проблемы является использование этого компаратора:

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

Извлечение ключа, т.е. IShopProduct::getVintage - это функция, используемая для извлечения ключа сортировки.

Ключевой компаратор, то есть Comparator.nullsLast(Comparator.naturalOrder()), используется для сравнения ключа сортировки.

Comparator.naturalOrder() здесь просто возвращает компаратор, который сравнивает Comparable объектов в естественном порядке.

0 голосов
/ 07 мая 2018

должно быть

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

Comparator.nullFirst()/nullLast() считают нулевое значение большим / меньшим, чем ненулевой объект

Редактировать

Это реализация 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(), поэтому он бросит NPE, если 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.

Значения будут переданы в компаратор naturalOrder() с разрешением в value1.compareTo(value2). Обычно он генерирует NPE, но мы обернули его Comparator.nullLast, у которого есть специальный обработчик null.

...