Java对列表中的列表进行排序

26

我该如何使用Collections.sort()或其他排序方法将Java中的列表排序成字典序?

private List<List<Integer>> possiblePoles = setPoles();    
System.out.println(possiblePoles)
[[1, 3, 5], [1, 2, 3]]

通过自己实现排序? - MikeCAT
不,可能是一个Java函数。 - user4780686
https://dev59.com/9E7Sa4cB1Zd3GeqP2U2o - developer033
5个回答

36
您需要实现自己的“Comparator”类,并将实例传递给“Collections.sort()”。
class ListComparator<T extends Comparable<T>> implements Comparator<List<T>> {

  @Override
  public int compare(List<T> o1, List<T> o2) {
    for (int i = 0; i < Math.min(o1.size(), o2.size()); i++) {
      int c = o1.get(i).compareTo(o2.get(i));
      if (c != 0) {
        return c;
      }
    }
    return Integer.compare(o1.size(), o2.size());
  }

}

那么排序就很容易了。
List<List<Integer>> listOfLists = ...;

Collections.sort(listOfLists, new ListComparator<>());

更好的是:由于Java使用类型擦除,您可以创建ListComparator的单例实例并进行不安全转换(它无状态)。 - Nayuki
@Nayuki,我宁愿不这样做,因为我不想一直携带实例,仅仅因为我用过它一次。内存占用可能很小,但创建对象的成本也很小。但每个人都可以随意选择做法 ^^ - MartinS
1
我会使用 int c = ObjectUtils.compare(o1.get(i), o2.get(i))。否则,如果 o1.get(i)==null,你将获得一个 NPE 错误。(ObjectUtils 是来自 Apache Commons 库) - Michael Anderson
特殊情况:如果列表是长链接列表,则通过索引访问效率低下。在这种情况下,应该优先使用两个迭代器。 - Ole V.V.

7
使用Java 8流API改进了MartinS的答案
possiblePoles = possiblePoles.stream().sorted((o1,o2) -> {
             for (int i = 0; i < Math.min(o1.size(), o2.size()); i++) {
                  int c = o1.get(i).compareTo(o2.get(i));
                  if (c != 0) {
                    return c;
                  }
                }
                return Integer.compare(o1.size(), o2.size());
         }).collect(Collectors.toList());

1

对于这个例子[[1,3],[1,2]],如果你想按照两个元素排序,你可以使用Java 8的sorted手动实现比较器方法,验证所有情况,例如以下示例:

List<List<Integer>> result = contests.stream().sorted((o1, o2) -> {
        if (o1.get(1) > o2.get(1) ||
            (o1.get(1).equals(o2.get(1)) && o1.get(0) > o2.get(0))) {
            return -1;
        } else if (o1.get(1) < o2.get(1) ||
            (o1.get(1).equals(o2.get(1)) && o1.get(0) < o2.get(0))) {
            return 1;
        }
        return 0;
    }).collect(Collectors.toList());

或者

contests.sort((o1, o2) -> {
                if (o1.get(1) > o2.get(1) ||
                    (o1.get(1).equals(o2.get(1)) && o1.get(0) > o2.get(0))) {
                    return -1;
                } else if (o1.get(1) < o2.get(1) ||
                    (o1.get(1).equals(o2.get(1)) && o1.get(0) < o2.get(0))) {
                    return 1;
                }
                return 0;
            });

0
  possiblePoles.sort((l1, l2) -> {
        int minLength = Math.min(l1.size(), l2.size());
        for (int i = 0; i < minLength; i++) {
            int lexicographicalPosition = l1.get(i).compareTo(l2.get(i));
            if (lexicographicalPosition != 0) {
                return lexicographicalPosition;
            }
        }
        return Integer.compare(l1.size(), l2.size());
    });

与Java 8相同的逻辑


0

尝试使用这段代码。

Collections.sort(list, (a,b) -> a.get(0) - b.get(0));


我相信这只对第一个元素进行排序。 - Ellen Spertus

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接