使用比较器对列表列表进行排序

can*_*ani 4 java sorting oop algorithm functional-programming

我正在考虑使用比较器整理出一个列表列表(在 ArrayLists 上)。订单最大的地方。所有子列表将始终具有相同的大小。

例如,一个列表

[[4,5,6], [7,9,10], [4,7,8], [1,2,3], [7,9,12]]
Run Code Online (Sandbox Code Playgroud)

这应该

[[7,9,12], [7,9,10], [4,7,8], [4,5,6], [1,2,3]]
Run Code Online (Sandbox Code Playgroud)

我有这样的东西,但只按每个列表中的第一项排序

List<List<Integer>> list = Arrays.asList(
                Arrays.asList(4,5,6),
                Arrays.asList(7,9,10), 
                Arrays.asList(4,7,8),
                Arrays.asList(1,2,3), 
                Arrays.asList(7,9,12));

list.sort((l1, l2) -> l2.get(0).compareTo(l1.get(0)));
Run Code Online (Sandbox Code Playgroud)

其中产生:

[[7, 9, 10], [7, 9, 12], [4, 5, 6], [4, 7, 8], [1, 2, 3]]
Run Code Online (Sandbox Code Playgroud)

如何编写比较器,如果前一项相等,则按列表中的下一项进行排序?

例如,[7, 9, 10], [7, 9, 12] 应该继续比较两个 7,然后是两个 9,然后是 10 和 12。例如,[4, 5, 6], [4, 7, 8] 应该继续比较两个 4,然后 4 和 7 并停止。

Ous*_* D. 6

您可以这样定义比较器:

Comparator<List<Integer>> comparator = (list1, list2) -> {
       for (int i = 0; i < list1.size(); i++) {
            int value = Integer.compare(list2.get(i), list1.get(i));
            if (value != 0)
                return value;
       }
       return 0;
};
Run Code Online (Sandbox Code Playgroud)

或者:

Comparator<List<Integer>> comparator = (list1, list2) -> 
IntStream.range(0, list1.size())
         .map(i -> Integer.compare(list2.get(i), list1.get(i)))
         .filter(value -> value != 0)
         .findFirst()
         .orElse(0);
Run Code Online (Sandbox Code Playgroud)

然后排序:

list.sort(comparator);
Run Code Online (Sandbox Code Playgroud)

更新

您可以通过创建一个返回比较器的自定义泛型函数来进一步概括这一点,即:

static <T extends Comparable<T>> Comparator<List<T>> comparator(){
       return (o1, o2) -> IntStream.range(0, o1.size())
                                   .map(i -> o2.get(i).compareTo(o1.get(i)))
                                   .filter(value -> value != 0)
                                   .findFirst()
                                   .orElse(0);
}
Run Code Online (Sandbox Code Playgroud)

现在你可以这样做:

List<List<Integer>> integerList = Arrays.asList(
                Arrays.asList(4,5,6),
                Arrays.asList(7,9,10),
                Arrays.asList(4,7,8),
                Arrays.asList(1,2,3),
                Arrays.asList(7,9,12));

integerList.sort(comparator()); // sort list of integers descending

List<List<String>> stringList = Arrays.asList(
                Arrays.asList("a","b","c"),
                Arrays.asList("d","e","f"),
                Arrays.asList("g","h","i"));

stringList.sort(comparator()); // sort list of strings descending 
Run Code Online (Sandbox Code Playgroud)

等等……

注意- 我使用的是 JDK 9+,所以我不知道类型推断在JDK 8之前的版本中是否足够好。