按两个不同的属性对集合进行排序

Sort collection by two different properties

我有一个 class,其中有多个属性,我希望它作为排序依据。目前我按 Name 排序是这样的:

Collections.sort(rowItems, new Comparator() {

    public int compare(Object o1, Object o2) {
        SearchRowItem p1 = (SearchRowItem) o1;
        SearchRowItem p2 = (SearchRowItem) o2;
        return p1.getName().compareToIgnoreCase(p2.getName());
    }

});

但我还想按 LastName 排序,次于 Name(所以如果名称相同,按 LastName 排序)。我如何将下面的代码与我的第一个排序结合起来以获得我描述的结果?

Collections.sort(rowItems, new Comparator() {

    public int compare(Object o1, Object o2) {
        SearchRowItem p1 = (SearchRowItem) o1;
        SearchRowItem p2 = (SearchRowItem) o2;
        return p1.getLastName().compareToIgnoreCase(p2.getLastName());
    }

});

在第一次比较中检查是否相等

public int compare(Object o1, Object o2) {
            SearchRowItem p1 = (SearchRowItem) o1;
            SearchRowItem p2 = (SearchRowItem) o2;
            int compare = p1.getName().compareToIgnoreCase(p2.getName());
            if (compare == 0) {
              compare = p1.getLastName().compareToIgnoreCase(p2.getLastName());
            }
            return compare;
        }

如果 getName() returns 0 这意味着两个对象具有相同的名称 - 只有这样你才应该使用 getLastName():

Collections.sort(rowItems, new Comparator() {

    @Override
    public int compare(Object o1, Object o2) {
        SearchRowItem p1 = (SearchRowItem) o1;
        SearchRowItem p2 = (SearchRowItem) o2;
        int nameComp =  p1.getName().compareToIgnoreCase(p2.getName());
        if (nameComp != 0) {
            return nameComp;
        }
        return p1.getLastName().compareToIgnoreCase(p2.getLastName());
    }
});

编辑:
上面的答案遵循 OP 的风格。但是,如果可能,您应该使用泛型来清理代码:

Collections.sort(rowItems, new Comparator<SearchRowItem>() {

    @Override
    public int compare(SearchRowItem p1, SearchRowItem p2) {
        int nameComp =  p1.getName().compareToIgnoreCase(p2.getName());
        if (nameComp != 0) {
            return nameComp;
        }
        return p1.getLastName().compareToIgnoreCase(p2.getLastName());
    }
});

一个简单的 Comparator 首先比较 name 然后 lastName 将与 Collections.sort 方法一起工作。

来自JavaDoc

Compares its two arguments for order. Returns a negative integer, zero, or a positive integer as the first argument is less than, equal to, or greater than the second.


因此,这里是比较两个属性的 Comparator 示例:

Collections.sort(rowItems, new Comparator<SearchRowItem>() {
    @Override
    public int compare(final SearchRowItem o1, final SearchRowItem o2) {
        int compare = o1.getName().compareToIgnoreCase(o2.getName());
        if (compare != 0) {
            return compare;
        }
        return o1.getLastName().compareToIgnoreCase(o2.getLastName());
    }
});

但是,还有其他选择。 Java 8 个引入的流,其中排序集成得很好。与新方法 Comparator.comparingthenCompare 一起,可以像这样创建一个不错的流。

final List<SearchRowItem> collect = rowItems.stream()
        .sorted(
                Comparator.comparing(SearchRowItem::getName, String::compareToIgnoreCase)
                          .thenComparing(SearchRowItem::getLastName, String::compareToIgnoreCase))
        .collect(Collectors.toList());

请注意,后者不会对原始 List 进行排序,而是创建一个新的排序列表。