Попытка использовать Comparator для сортировки по имени, игнорировать регистр, а также нулевые значения в первую очередь

У меня проблемы с использованием класса Java 8 Comparator для сортировки списка элементов.

Мой текущий рабочий компаратор ниже:

comparator = Comparator.comparing(Person::getName, Comparator.nullsFirst(Comparator.naturalOrder()));

Это работает: сначала упорядочивает список по имени с нулевыми значениями. Тем не менее, я сейчас пытаюсь игнорировать регистр имен.

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

Глядя онлайн, похоже, я должен использовать String.CASE_INSENSITIVE_ORDER, но единственные примеры, которые я вижу, не включают спецификацию нулевого порядка.

Я могу сделать что-то вроде этого:

comparator = Comparator.comparing(Person::getName, String.CASE_INSENSITIVE_ORDER);

Однако всякий раз, когда я пытаюсь включить Comparator.nullsFirst Я заканчиваю тем, что получаю ошибки типа, и не понимаю, как продолжить.

Я пытался сделать цепочку, похожую на

thenComparing(Comparator.nullsFirst(Comparator.naturalOrder))

но это тоже не работает.

Может ли кто-нибудь дать мне несколько советов о том, как я могу связать их вместе, чтобы отсортировать по имени (без учета регистра), а затем упорядочить нули. Я, кажется, путаю себя с типами.

1 ответ

Есть два типа null s вы можете иметь в своем списке. Вы можете иметь nullPerson ссылки, и вы можете иметь Person с null имена.

В первом случае вы должны подать заявку nullsFirst к базовому компаратору, который вы хотите использовать:

comparator = Comparator.nullsFirst(
        Comparator.comparing(Person::getName, String.CASE_INSENSITIVE_ORDER));

Если у вас есть возможность null имена, вы должны убедиться, что ваш ключ никогда не возвращает null или что вы подаете заявку nullsFirst в String.CASE_INSENSITIVE_ORDER, Второй вариант, конечно, намного проще:

comparator = Comparator.comparing(
        Person::getName, Comparator.nullsFirst(String.CASE_INSENSITIVE_ORDER));

Если у вас есть оба варианта (null ссылки и null имена), вам придется объединить обе версии и применить nullsFirst дважды:

comparator = Comparator.nullsFirst(
        Comparator.comparing(
                Person::getName,
                Comparator.nullsFirst(String.CASE_INSENSITIVE_ORDER)
        )
);

Если вы объединяете несколько сравнений, как это, внешний nullsFirst, который гарантирует, что nullPerson s сортируются правильно, могут применяться ко всей цепочке:

comparator = Comparator.nullsFirst(
        Comparator.comparing(
                Person::getName,
                Comparator.nullsFirst(String.CASE_INSENSITIVE_ORDER)
        ).thenComparing(...)
);
Другие вопросы по тегам