У нас есть некоторый код, который сортирует список адресов на основе расстояния между их координатами. это сделано через collections.sort с пользовательским компаратором.
Однако время от времени адрес без координат находится в списке, вызывающем NullPointerException. Моя начальная идея зафиксировать это состояла в том, чтобы иметь возврат компаратора 0 как dististance для адресов, где по крайней мере одна из координат является пустой. Я боюсь, что это могло бы привести к повреждению порядка 'допустимые' элементы в списке.
так возвращается '0' значения для пустых данных в компараторе хорошо или там более чистый способ разрешить это.
Обращайтесь с ним, как с null
, означающим бесконечно далекое расстояние. Таким образом:
comp(1234, null) == -1
comp(null, null) == 0
comp(null, 1234) == 1
Таким образом, получается последовательное упорядочение.
Я считаю, что все, что вы пытаетесь сделать чтобы «исправить» нулевые
координаты - это просто закрашивание трещин. Что вам действительно нужно сделать, так это найти и исправить ошибки, которые вводят ложные нулевые
координаты.
По моему опыту, заражение NPE-ошибками часто вызывается следующими плохими привычками кодирования:
null
, чтобы избежать создания пустых массивов или коллекций, null
, когда должно было быть сгенерировано исключение, или null
для представления «нет значения», когда есть лучшее решение.(Лучшие решения проблемы «без значения» обычно включают в себя переписывание кода, чтобы вам не требовалось для его представления и / или использование вместо него ненулевого значения; например, пустая строка, специальный экземпляр, зарезервированное значение. Вы не всегда можете найти лучшее решение, но часто можете.)
Если это описывает ваше приложение, вам следует потратить время на устранение проблем кода, а не думать о способах скрыть НПЭ.
Возможно, вы не захотите возвращать 0, так как это подразумевает, что адреса равноудалены, а вы этого не знаете. Это классическая проблема, когда вы пытаетесь справиться с плохими входными данными. Я не думаю, что в обязанности компаратора входит попытка определить, насколько далеко находится адрес в реальном выражении, когда вы не знаете расстояние. Я бы удалил эти адреса из списка перед сортировкой.
Хак заключается в перемещении их в нижнюю часть списка (но это некрасиво!)
.Нет, чище нет. Возможно:
Но что более важно - постарайтесь избавиться / заполнить недостающие координаты, или, лучше: не помещайте адреса с пропущенными координатами в список.
На самом деле, не заносить их в список - наиболее логичное поведение. Если вы поместите их в список, результат не будет упорядочен по расстоянию.
Вы можете создать другой список, содержащий адреса с отсутствующими координатами, и дать понять, кому нужна эта информация (конечный пользователь, пользователь API), что первый список содержит только адреса с необходимыми данными, а второй список содержит адреса, по которым отсутствует необходимая информация.
Вместо того, чтобы смотреть на это как на техническую проблему с компаратором, лучше еще раз взглянуть на требования: что вы на самом деле пытаетесь сделать здесь, что вы собираетесь делать с этим отсортированным списком?
Как вы уже понимаете, всегда возвращать 0, когда один из них имеет значение null, здесь не очень хорошая идея; это действительно может испортить результат. Но то, что вам следует делать, зависит от того, что вам нужно, а не от того, что обычно делают / нужно другим. То, как ваша программа ведет себя с адресами, у которых нет местоположения (то есть то, что увидит пользователь), не должно зависеть от некоторых технических деталей, таких как "лучшая практика" для компараторов. вопрос о том, какая здесь «лучшая практика» звучит как вопрос о том, какие «лучшие требования»).
Я лично ненавижу иметь дело с особыми нулевыми случаями повсюду в моих компараторах, поэтому я искал более чистое решение и наконец нашел коллекции google. Их упорядочивание просто потрясающее. Они поддерживают составные компараторы, предлагают сортировать нули сверху и в конец и позволяют выполнять определенные функции перед сравнением. Написание компараторов еще никогда не было таким простым. Вам стоит попробовать.
Чтобы расширить ответ Вилли Шенборна, я пришел сюда, чтобы сказать, что google-collections - это именно то, что вам нужно.
В общем случае вы можете просто написать свой собственный Компаратор
, чтобы игнорировать нули (предположить, что он не равен нулю, чтобы он мог сосредоточиться на важной логике), а затем использовать Упорядочивание для обработки нулей:
Collections.sort(addresses, Ordering.from(new AddressComparator()).nullsLast());
В вашем случае, однако, это данные ВНУТРИ Адреса (Координаты), которые используются для сортировки, верно? google-collections даже больше полезен в этом случае. Так что у вас может быть что-то более похожее на:
// Seems verbose at first glance, but you'll probably find yourself reusing
// this a lot and it will pay off quickly.
private static final Function<Address, Coordinates> ADDRESS_TO_COORDINATES =
new Function<Address, Coordinates>() {
public Coordinates apply(Address in) {
return in.getCoordinates();
}
};
private static final Comparator<Coordinates> COORDINATE_SORTER = .... // existing
, тогда, когда вы захотите сортировать:
Collections.sort(addresses,
Ordering.from(COORDINATE_SORTER)
.nullsLast()
.onResultOf(ADDRESS_TO_COORDINATES));
, и здесь сила google-коллекций действительно начинает окупаться.