根据其中一个字段对对象列表进行排序

3

你好,stackoverflow社区!我是新来的,也是相对于Java和Android编程比较新的人,这也是我的问题所涉及的对象,所以提前道歉如果有任何错误!

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

https://dev59.com/dlTTa4cB1Zd3GeqPuamC#5113108

但我实际上很难让它起作用。我怀疑我可能由于缺乏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个回答

8

如果两个对象不相等,那么在Comparator.compare方法中不应该返回0。根据API文档,“这是可以的”,但并不是鼓励这样做:

通常情况下(compare(x, y)==0) == (x.equals(y)),但不是强制要求。一般来说,任何违反此条件的比较器都应清楚地指出这一事实。建议使用的语言是“注意:此比较器施加的排序与equals方法不一致。”


在我看来,你应该为每个字段返回一个特定的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);
}

谢谢您!我包含了“return 0”的原因是因为Eclipse告诉我该方法必须返回一个整数,而我不确定该放什么。对于C++背景的人来说,这是一个更简单易懂的实现方式!再次感谢您! - user1549672

0

你能贴出不起作用的调用代码吗?我在你提供的代码中没有看到明显的错误。

首先,你可以尝试添加一个额外的else条件,像这样:

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

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

传递字段的更可靠方法是声明枚举:

enum ItemLocationField {
    TITLE,
    ID
}

那么你的条件将变为:

if (field == ItemLocationField.TITLE)

等等。这将减少出现拼写错误的机会(编译器会告诉你是否有错误)。


0
除了“返回0”和使用“equals”比较参数之外,我没有看到任何问题。您可以通过使用“抛出RuntimeException”而不是“返回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 .");
        }
    });
}

我认为这主要是由于我对Java缺乏经验...Eclipse告诉我实现必须返回一个整数! - user1549672

0

1. 如果您想根据一个属性对对象进行排序,则可以使用java.lang.Comparable接口以及Collections.sort(List<T> list)

2. 如果您想根据多个属性对对象进行排序,则可以使用java.util.Comparator接口以及Collections.sort(List<T> list, Comparator<? super T> c)


谢谢!我主要是在寻找一种基于包含多个属性的对象的一个属性进行排序的方法! - user1549672
是的,这就是我第一个建议所提到的...... 根据一个属性进行排序。第二个点是额外知识的补充。 - Kumar Vivek Mitra

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接