3

你好 stackoverflow 社区!我是这些论坛的新手,对 java 和 android 编程也很陌生——这恰好是我的问题的对象——对于任何错误,请提前道歉!

我的问题是排序。我正在寻找一种基于我选择的字段对对象进行排序的方法(不是基于第一个字段排序,然后是下一个字段,等等,例如比较器链接)。我相信我已经找到了解决问题的方法:

https://stackoverflow.com/a/5113108/1549672

但我实际上很难让它发挥作用。我怀疑由于缺乏 Java 经验,我可能遗漏了一些东西,所以欢迎任何帮助!

这是我正在尝试的:

作为我的班级——

public class ItemLocation {
String title;
int id;
}

作为我的功能-

public void sort(final String field, List<ItemLocation> itemLocationList) {
    Collections.sort(itemLocationList, new Comparator<ItemLocation>() {
        @Override
        public int compare(ItemLocation o1, ItemLocation o2) {
            if(field.equals("title")) {
                return o1.title.compareTo(o2.title);
            } else if(field.equals("id")) {
                return Integer.valueOf(o1.id).compareTo(o2.id);
            }
            return 0;
        }
    });
}

使用这些,有人可以举一个使用这种方法的例子吗?我试图填充一个 ArrayList 并对其进行排序,但无济于事。

谢谢您的帮助!

4

4 回答 4

8

如果它们不相等,则不0应从该方法返回。Comparator.compare从 API 文档来看,合同是“好的”,但并不完全鼓励:

通常是这样,但并不严格要求 (compare(x, y)==0) == (x.equals(y))。一般来说,任何违反此条件的比较器都应清楚地表明这一事实。推荐的语言是“注意:这个比较器强加了与等于不一致的排序。”


Comparator在我看来,您应该为每个字段返回一个特定的值:

Comparator<ItemLocation> titleComparator = new Comparator<ItemLocation>() {
    @Override
    public int compare(ItemLocation o1, ItemLocation o2) {
        return o1.title.compareTo(o2.title);
    }
}

Comparator<ItemLocation> idComparator = new Comparator<ItemLocation>() {
    @Override
    public int compare(ItemLocation o1, ItemLocation o2) {
        return Integer.valueOf(o1.id).compareTo(o2.id);
    }
}

public void sort(final String field, List<ItemLocation> itemLocationList) {

    final Comparator<ItemLocation> comparator;

    if(field.equals("title")) {
        comparator = titleComparator;
    } else if (field.equals("id")) {
        comparator = idComparator;
    } else {
        throw new IllegalArgumentException("Comparator not found for " + field);
    }

    Collections.sort(itemLocationList, comparator);
}
于 2012-08-02T11:11:24.267 回答
0

您可以发布不起作用的调用代码吗?我看不出您提供的代码有任何明显错误。

首先,您可以尝试添加一个额外的 else 案例,如下所示:

else {
    throw new IllegalArgumentException("Unrecognised field name");
}

目前,如果您的调用代码中有拼写错误,比较器将始终返回 0,这将使列表未排序。

传递字段的一种更强大的方法是声明一个枚举:

enum ItemLocationField {
    TITLE,
    ID
}

那么您的条件将变为:

if (field == ItemLocationField.TITLE)

等等。这将减少打错字的机会(编译器会告诉你是否这样做)。

于 2012-08-02T11:13:42.233 回答
0

除了returning 0将参数与equals. 您可以通过throwing RuntimeException而不是returning 0和使用equalsIgnoreCase而不是equals方法来改进它,最好忽略参数的大小写。

public static void sort(final String field, List<ItemLocation> itemLocationList) {
    Collections.sort(itemLocationList, new Comparator<ItemLocation>() {
        @Override
        public int compare(ItemLocation o1, ItemLocation o2) {
            if(field.equalsIgnoreCase("title")) {
                return o1.title.compareTo(o2.title);
            } else if(field.equalsIgnoreCase("id")) {
                return Integer.valueOf(o1.id).compareTo(o2.id);
            }else
                throw new IllegalArgumentException("Invalid Parameter .");
        }
    });
}
于 2012-08-02T11:20:33.340 回答
0

1.如果您只想根据一个属性对对象进行排序,那么请选择java.lang.Comparable接口Collections.sort(List<T> list)

2.如果要根据多个属性对对象进行排序,请选择 java.util.Comparator接口Collections.sort(List<T> list, Comparator<? super T> c)

于 2012-08-02T12:11:56.827 回答