有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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

我有一份清单:

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

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

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

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

谢谢


共 (4) 个答案

  1. # 1 楼答案

    假设than"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数字。但这超出了这个问题的范围;发布一个新的,让不那么忙的程序员练习虚拟速度编码

  2. # 2 楼答案

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

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

    这样,您的列表将是List<Item>。现在您可以简单地使用Collections.sort(list, yourComparator),或者如果您使用的是java8 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));
    
  3. # 3 楼答案

    正如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,所以您只需排序:不需要比较器

    Collections.sort(list);
    
  4. # 4 楼答案

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

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