简体   繁体   English

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

[英]Sorting Java List by items in sublist

I have a list: 我有一个清单:

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

And I would like to sort it by second value in subarray, if there is two a like then it should sort by third value and if it finds two a like from there then it should sort them by first element. 我希望用子流中的第二个值对它进行排序,如果有两个像,那么它应该按第三个值排序,如果它从那里找到两个,那么它应该按第一个元素排序。 So final result should look like that: 所以最终结果应该是这样的:

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

Can someone show me some good way to do it? 有人能告诉我一些好方法吗?

Thanks! 谢谢!

["a", "one", 3] should be instance of your class like ["a", "one", 3]应该是你班级的实例

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

This way your list would be List<Item> . 这样你的列表就是List<Item> Now you can simply use Collections.sort(list, yourComparator) or if you are using Java 8 list.sort(yourComparator) . 现在您可以使用Collections.sort(list, yourComparator)或者使用Java 8 list.sort(yourComparator)

As yourComparator you can pass instance of class implementing Comparator interface, for instance in a way 作为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());
    }
};

But probably more readable and possibly easier approach would be creating separate comparators for each field and combining them. 但是可能更具可读性且可能更容易的方法是为每个字段创建单独的比较器并将它们组合起来。 If you are using Java 8 your code can look like: 如果您使用的是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));

A good way to do this? 这样做的好方法? Not the way you're thinking. 不是你想的那样。 A List of Lists is too primitive; 列表清单太原始了; a List of custom objects would be better. 自定义对象列表会更好。

Write custom Comparators for the cases you want to run. 为您要运行的案例编写自定义比较器。

Supposing than "one" is less than "two" (since "o" < "t" ), and I do not see any other "string numerics"* here, a simple comparator can be written: 假设"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));
    }
}

Then sort using this comparator: 然后使用此比较器排序:

Collections.sort(list, c);

*For other "string numerics" such as "three", "four" and so on, if you need them to be compared by meaning, not lexographically, you would need to define special mapping, which would convert its "meaning" to Integer number. *对于其他“字符串数字”,如“三”,“四”等,如果你需要通过意义进行比较,而不是通过词法,你需要定义特殊的映射,将其“含义”转换为Integer数。 But this is out of scope of this question; 但这超出了这个问题的范围; post a new one to let not-so-busy programmers practice in dummy speed coding. 发布一个新的,让不那么繁忙的程序员在虚拟速度编码中练习。

As duffymo suggests, use a list of Objects. 正如duffymo建议的那样,使用对象列表。 A simple struct will do: 一个简单的结构将做:

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;

Since the struct implements Comparable, you can just sort: No need for a Comparator. 由于struct实现了Comparable,你只需排序:不需要Comparator。

Collections.sort(list);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM