按子列表中的项目对Java List进行排序

时间:2015-04-20 20:32:35

标签: java list sorting arraylist

我有一个清单:

List<List<Item>> = [["a", "one", 3], ["b", "one", 2], ["c", "one", 4], ["d", "two", 2],["e", "one", 1], ["f", "two", 1]]

我想用子数组中的第二个值对它进行排序,如果有两个类似的那么它应该按第三个值排序,如果它从那里找到两个像那么它应该按第一个元素排序它们。 所以最终结果应该是这样的:

[["e", "one", 1], ["b", "one", 2], ["a", "one", 3], ["c", "one", 4], ["f", "two", 1], ["d", "two", 2]]

有人能告诉我一些好方法吗?

谢谢!

4 个答案:

答案 0 :(得分:3)

["a", "one", 3]应该是您的类的实例,如

class Item{
    private String val1;
    private String val2;
    private int val3;
    //getters and setters
}

这样您的列表就是List<Item>。现在您只需使用Collections.sort(list, yourComparator)或者使用Java 8 list.sort(yourComparator)

作为yourComparator,您可以传递实现Comparator接口的类的实例,例如以某种方式

Comparator<Item> yourComparator = new Comparator<Item>() {

    @Override
    public int compare(Item o1, Item o2) {
        //comapre val2
        int result = o1.getVal2().compareTo(o2.getVal2());
        if (result != 0) return result;

        //if we are here val2 in both objects ware equal (result was 0)
        result = Integer.compare(o1.getVal3(), o2.getVal3());
        if (result != 0) return result;

        return o1.getVal1().compareTo(o2.getVal1());
    }
};

但可能更具可读性和可能更简单的方法是为每个字段创建单独的比较器并将它们组合起来。如果您使用的是Java 8,则代码可能如下所示:

Comparator<Item> val1Comparator = Comparator.comparing(Item::getVal1);
Comparator<Item> val2Comparator = Comparator.comparing(Item::getVal2);
Comparator<Item> val3Comparator = Comparator.comparingInt(Item::getVal3);


list.sort(val2Comparator
        .thenComparing(val3Comparator)
        .thenComparing(val1Comparator));

答案 1 :(得分:2)

这样做的好方法?不是你想的那种方式。列表清单太原始了;自定义对象列表会更好。

为您要运行的案例编写自定义比较器。

答案 2 :(得分:2)

假设"one"小于"two"(自"o" < "t"起),我在这里看不到任何其他“字符串数字”*,可以写一个简单的比较器:

Comparator<List<Item>> c = new Comparator<List<Item>>() {

    int[] order = new int[]{1, 2, 0};  // order to compare: 2nd, then 3rd, finally 1st

    @Override
    public int compare(List<Item> l1, List<Item> l2) {
        for (int i = 0; i < order.length - 1; i++) {  
           int result = l1.get(i).compareTo(l2.get(i));
           if (result != 0)   // means that i-th elements are not the same
               return result;
        }
        return l1.get(order.length - 1).compareTo(l2.get(order.length - 1));
    }
}

然后使用这个比较器排序:

Collections.sort(list, c);

*对于其他“字符串数字”,如“三”,“四”等,如果你需要通过意义进行比较,而不是通过词汇表,你需要定义特殊的映射,这将转换其“意义” “到Integer号。但这超出了这个问题的范围;发布一个新的程序员让不那么繁忙的程序员练习虚拟速度编码。

答案 3 :(得分:0)

正如duffymo建议的那样,使用一个对象列表。一个简单的结构将会:

class Triple implements Comparable<Triple> {
    Item first;
    Item second;
    Item third;

    int compareTo(Triple other) {
        int second = compare(this.second, other.second);
        if (second == 0) {
            int third = compare(this.third, other.third);
            if (third == 0) {
                return compare(this.first, other.first);
            }
            return third;
        }
        return second;
    }

    static int compare(Item lhs, Item rhs) {
        /* Do your compare here! */
    }
}
List<Triple> list;

由于struct实现了Comparable,你只需排序:不需要Comparator。

Collections.sort(list);