компаратор с нулевыми значениями

У нас есть некоторый код, который сортирует список адресов на основе расстояния между их координатами. это сделано через collections.sort с пользовательским компаратором.

Однако время от времени адрес без координат находится в списке, вызывающем NullPointerException. Моя начальная идея зафиксировать это состояла в том, чтобы иметь возврат компаратора 0 как dististance для адресов, где по крайней мере одна из координат является пустой. Я боюсь, что это могло бы привести к повреждению порядка 'допустимые' элементы в списке.

так возвращается '0' значения для пустых данных в компараторе хорошо или там более чистый способ разрешить это.

55
задан skaffman 8 March 2010 в 03:39
поделиться

7 ответов

Обращайтесь с ним, как с null, означающим бесконечно далекое расстояние. Таким образом:

  • comp(1234, null) == -1
  • comp(null, null) == 0
  • comp(null, 1234) == 1

Таким образом, получается последовательное упорядочение.

76
ответ дан 7 November 2019 в 07:11
поделиться

Я считаю, что все, что вы пытаетесь сделать чтобы «исправить» нулевые координаты - это просто закрашивание трещин. Что вам действительно нужно сделать, так это найти и исправить ошибки, которые вводят ложные нулевые координаты.

По моему опыту, заражение NPE-ошибками часто вызывается следующими плохими привычками кодирования:

  • неадекватная проверка входных параметров,
  • использование null , чтобы избежать создания пустых массивов или коллекций,
  • , возвращающий null , когда должно было быть сгенерировано исключение, или
  • с использованием null для представления «нет значения», когда есть лучшее решение.

(Лучшие решения проблемы «без значения» обычно включают в себя переписывание кода, чтобы вам не требовалось для его представления и / или использование вместо него ненулевого значения; например, пустая строка, специальный экземпляр, зарезервированное значение. Вы не всегда можете найти лучшее решение, но часто можете.)

Если это описывает ваше приложение, вам следует потратить время на устранение проблем кода, а не думать о способах скрыть НПЭ.

8
ответ дан 7 November 2019 в 07:11
поделиться

Возможно, вы не захотите возвращать 0, так как это подразумевает, что адреса равноудалены, а вы этого не знаете. Это классическая проблема, когда вы пытаетесь справиться с плохими входными данными. Я не думаю, что в обязанности компаратора входит попытка определить, насколько далеко находится адрес в реальном выражении, когда вы не знаете расстояние. Я бы удалил эти адреса из списка перед сортировкой.

Хак заключается в перемещении их в нижнюю часть списка (но это некрасиво!)

.
3
ответ дан 7 November 2019 в 07:11
поделиться

Нет, чище нет. Возможно:

  • , если координаты обоих сравниваемых объектов равны нулю, вернуть 0
  • , если координаты одного из объектов равны нулю, вернуть -1 / 1 (в зависимости от того, является ли это первым или вторым аргументом)

Но что более важно - постарайтесь избавиться / заполнить недостающие координаты, или, лучше: не помещайте адреса с пропущенными координатами в список.

На самом деле, не заносить их в список - наиболее логичное поведение. Если вы поместите их в список, результат не будет упорядочен по расстоянию.

Вы можете создать другой список, содержащий адреса с отсутствующими координатами, и дать понять, кому нужна эта информация (конечный пользователь, пользователь API), что первый список содержит только адреса с необходимыми данными, а второй список содержит адреса, по которым отсутствует необходимая информация.

1
ответ дан 7 November 2019 в 07:11
поделиться

Вместо того, чтобы смотреть на это как на техническую проблему с компаратором, лучше еще раз взглянуть на требования: что вы на самом деле пытаетесь сделать здесь, что вы собираетесь делать с этим отсортированным списком?

  • Если вы пытаетесь отсортировать их, чтобы сначала показать пользователю наиболее подходящие решения, было бы неплохо поместить неизвестные местоположения в последнюю очередь, так что относитесь к он похож на бесконечность (возвращает 0 / -1 / 1 в зависимости от того, какое из них равно нулю).
  • Если вы собираетесь использовать этот результат, чтобы нарисовать какой-то график или выполнить другие вычисления, которые зависят от того, действительно ли они отсортированы по расстоянию, то нулей, вероятно, в любом случае не должно было быть (так что либо сначала удалите их, или выбросить исключение, если в этот момент на самом деле не должно было быть никаких адресов с нулевым местоположением).

Как вы уже понимаете, всегда возвращать 0, когда один из них имеет значение null, здесь не очень хорошая идея; это действительно может испортить результат. Но то, что вам следует делать, зависит от того, что вам нужно, а не от того, что обычно делают / нужно другим. То, как ваша программа ведет себя с адресами, у которых нет местоположения (то есть то, что увидит пользователь), не должно зависеть от некоторых технических деталей, таких как "лучшая практика" для компараторов. вопрос о том, какая здесь «лучшая практика» звучит как вопрос о том, какие «лучшие требования»).

1
ответ дан 7 November 2019 в 07:11
поделиться

Я лично ненавижу иметь дело с особыми нулевыми случаями повсюду в моих компараторах, поэтому я искал более чистое решение и наконец нашел коллекции google. Их упорядочивание просто потрясающее. Они поддерживают составные компараторы, предлагают сортировать нули сверху и в конец и позволяют выполнять определенные функции перед сравнением. Написание компараторов еще никогда не было таким простым. Вам стоит попробовать.

1
ответ дан 7 November 2019 в 07:11
поделиться

Чтобы расширить ответ Вилли Шенборна, я пришел сюда, чтобы сказать, что 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-коллекций действительно начинает окупаться.

24
ответ дан 7 November 2019 в 07:11
поделиться
Другие вопросы по тегам:

Похожие вопросы: