按字符串属性对自定义类型数组进行排序?

时间:2011-02-03 00:10:15

标签: java string sorting

我有一个自定义类型的数组,我想按其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 个答案:

答案 0 :(得分:2)

一个问题一开始 - 如果您给两名患有空名称的患者或两名空患者参考,您的比较器就会不一致。特别是:

Patient p1 = null;
Patient p2 = null;

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

xy 的迹象应该不同 - 但它们都是-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 :(得分:1)

我假设你想要自然的字符串排序。

首先,就像它一样,你的compareTo分支给出了反转的结果。不知道这是不是你的意图(正如你所说的,当p1的字符串低于p2时,p1大于p2)。

此外,您可以放弃if的.equals分支。 compareTo已经处理了这种情况。

因此简单

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)

就足够了。

答案 2 :(得分:1)

您希望患者按姓氏按字母顺序排序,无效患者和前排空姓?

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);
        }
}

为了保持稳定,当姓氏相同时,它应该通过其他一些字段排序,例如名字。

答案 3 :(得分:0)

我会使用GuavaOrdering类:

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();