Возникли проблемы со сравнением двух продуктов. Я хочу сравнить винтажный (необязательный) атрибут каждого из них. Но всякий раз, когда этот атрибут имеет значение 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());
}
заранее спасибо
Ознакомьтесь со стандартным руководством по стилю Java. Люди с большей вероятностью помогут вам, если их не будут отвлекать идиосинкразические проблемы со стилем. В частности, ненужные пробелы и тот факт, что строка такая длинная, что мне приходится прокручивать по горизонтали




Так должно быть
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.
Спасибо! Почему мне нужен naturalOrder как второй параметр?
Эта перегрузка метода сравнение вызовет исключение, если переданной функцией извлечения ключа является null или извлеченное свойство - null. Поскольку вы упомянули, что свойство vintage иногда может быть null, это является причиной исключения NullPointerException.
Альтернативой для решения этой проблемы является использование этого компаратора:
Comparator<IShopProduct> comparator =
Comparator.comparing(IShopProduct::getVintage,
Comparator.nullsLast(naturalOrder()));
Функция извлечения ключей, то есть IShopProduct::getVintage, используется для извлечения ключа сортировки.
Компаратор ключей, то есть Comparator.nullsLast(Comparator.naturalOrder()), используется для сравнения ключа сортировки.
Comparator.naturalOrder() здесь просто возвращает компаратор, который сравнивает объекты Comparable в естественном порядке.
есть ли шанс, что
product1.getProvidedProductData()вернет null?