Сортировка массива пользовательских типов по строковому атрибуту? - PullRequest
0 голосов
/ 03 февраля 2011

У меня есть массив пользовательского типа, который я хочу отсортировать по одному из его атрибутов String.По какой-то причине следующий код дает неправильные результаты.Не могли бы вы указать, где я мог ошибиться?

class PatientLNComparator implements Comparator<Patient>{
        @Override
        public int compare(Patient p1, Patient p2) {
            String p1_LN = (p1 == null) ? null : p1.last_name;
            String p2_LN = (p2 == null) ? null : p2.last_name;

            if(p2_LN == null)
                    return -1;
            else if(p1_LN == null)
                    return +1;
            else if(p1_LN.equals(p2_LN))
                    return 0;
            else if(p1_LN.compareTo(p2_LN) > 0)
                    return -1;
            else
                    return +1;
        }
}

Ответы [ 4 ]

2 голосов
/ 03 февраля 2011

Одна проблема для начала - ваш компаратор будет непоследователен, если вы дадите ему двух пациентов с нулевыми именами или двух нулевых ссылок на пациентов. В частности:

Patient p1 = null;
Patient p2 = null;

int x = comparator.compare(p1, p2);
int y = comparator.compare(p2, p1);

Знаки x и y должны отличаться, но оба они будут равны -1.

После этого все зависит от того, как вы хотите сравнить имена. Я бы обычно использовал

return p1_LN.compareTo(p2_LN);

, если вы хотите отсортировать по возрастанию. Обратите внимание, что для сортировки в порядке по убыванию вы не должны просто возвращать -p1_LN.compareTo(p2_LN), так как если сравнение возвращает Integer.MIN_VALUE, отрицание не будет работать. Вместо этого вы хотите вернуть p2_LN.compareTo(p1_LN);.

Обратите внимание, что если вы используете эту схему, вам также не нужно звонить p1_LN.equals(p2_LN) - это будет обработано вызовом compareTo.

1 голос
/ 03 февраля 2011

Вы хотите, чтобы пациент был упорядочен в алфавитном порядке по фамилии, пустым пациентам и пустым фамилиям?

class PatientLNComparator implements Comparator<Patient>{
        @Override
        public int compare(Patient p1, Patient p2) {
            String p1_LN = (p1 == null) ? null : p1.last_name;
            String p2_LN = (p2 == null) ? null : p2.last_name;

            if (p1_LN == null && p2_LN == null)
                    return 0;
            else if (p2_LN == null)
                    return -1;
            else if(p1_LN == null)
                    return +1;
            else
                    return p1_LN.compareTo(p2_LN);
        }
}

Чтобы быть стабильным, он действительно должен упорядочиваться по некоторым другим полям, например по имени, когда фамилии равны.

1 голос
/ 03 февраля 2011

Полагаю, вы хотите для этого упорядочить натуральные строки.

Прежде всего, ваша ветвь сравнения дает инвертированные результаты. Не знаю, предназначено ли это для вас или нет (как вы говорите, p1 больше p2, когда строка p1 меньше p2).

Кроме того, вы можете выбросить ветвь .equals из if. Сравнение уже обрабатывает этот случай.

Поэтому простой

if(p2_LN == null && p1_LN == null)
    return 0;
else if(p1_LN == null)
    return +1;
else if(p2_LN == null)
    return -1;
else return p1_LN.compareTo(p2_LN)

будет достаточно.

0 голосов
/ 03 февраля 2011

Я бы использовал Гуава Классификация для этого:

class Patient {
    // ...
    public static final Function<Patient, String> GET_LAST_NAME =
        new Function<Patient, String>() {
            public String apply(Patient from) {
                if (from == null) return null;
                return from.last_name;
            }
        };

    public static final Comparator<Patient> BY_LAST_NAME =
        Ordering.natural()
                .onResultOf(GET_LAST_NAME)
                .nullsFirst();
}

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

    public static final Comparator<Patient> BY_LAST_NAME =
        Ordering.natural()
                .onResultOf(GET_LAST_NAME)
                .compound(Ordering.natural().onResultOf(GET_FIRST_NAME))
                .nullsFirst();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...