【问题标题】:How to sort using Collections.sort when having several fields?有多个字段时如何使用 Collections.sort 进行排序?
【发布时间】:2021-06-14 10:51:43
【问题描述】:

我有一个这样的 ArrayList:

ArrayList<Person> list;

Person 类型可以有一个name 和一个number,两者都是Strings。我希望使用以下表达式按降序对数字字符串(不是名称)进行排序:

Collections.sort(somelist, Collections.reverseOrder());

如何指定要按数字字段排序?

我可以通过 Person.getNumber() 获取号码;

【问题讨论】:

  • 你想按数字或词法对数字字段(你说的是字符串!)进行排序吗?

标签: java sorting arraylist


【解决方案1】:

你可能需要这个。

Collections.sort(list, 
            Comparator.comparingInt((Person p) -> Integer.valueOf(p.getNumber())).reversed());

如果我们需要使用其他字段对两者进行排序,那么以下内容会有所帮助。

Collections.sort(list, 
            Comparator.comparingInt((Person p) -> Integer.valueOf(p.getNumber()))
            .thenComparing(p -> p.getName()).reversed());

【讨论】:

  • 这不是一个稳定的排序.. 如果两个人的名字不同但编号相同,则顺序可以翻转。需要加thenComparing(p.getName())
  • 没错,但问题只问数字比较。
【解决方案2】:

您给出的示例是使用reverse() 方法,它在传递给Collections.sort() 时给出Comparator&lt;Person&gt;,在这种情况下定义为反转Comparable&lt;Person&gt; 的自然顺序。所以你的Person 类必须实现Comparable&lt;Person&gt; - 虽然不幸的是在编译时没有检测到这一点(但这个要求在javadoc中有描述)。

因此,要按任何内容(单个或多个字段)排序,您可以实现 Comparable&lt;Person&gt; 接口,或者可以实现 Comparator&lt;Person&gt; 的某些东西 - 就像之前在 SO 问题 Collections.sort with multiple fields 中提出的那样。

通常你应该实现一个稳定的比较 (Stable sort - do we really need it?) - 即如果两个对象具有相同的编号但不同的名称会发生​​什么 - 它们如何排序?如果在给出两个输入时没有得到相同的相对位置(a before bb after a),但顺序不同,那么它就不稳定,并且每次排序时不一定会得到相同的结果(如果一个的值是骗子)。所以这是执行compare 方法的老派 方法(假设您的数据中不能有null 引用)。

public int compare(final Person a, final Person b) {
  final int comp = a.getNumber().compareTo(b.getNumber());
  if (0 == comp) {
    return a.getName().compareTo(b.getName());
  }
  return comp;
}

这是一个 lambda 样式示例,包括创建 Comparator (HT @Preston) -

Collections.sort(list, 
            Comparator.comparingInt((Person p) -> Integer.valueOf(p.getNumber()))
            .thenComparing(p -> p.getName()).reversed());

【讨论】:

    猜你喜欢
    • 2012-07-15
    • 1970-01-01
    • 1970-01-01
    • 2017-03-05
    • 2011-05-14
    • 2011-06-12
    • 1970-01-01
    • 2021-11-05
    相关资源
    最近更新 更多