如何通过某些属性对对象列表进行sorting

我有简单的课程

public class ActiveAlarm { public long timeStarted; public long timeEnded; private String name = ""; private String description = ""; private String event; private boolean live = false; } 

List<ActiveAlarm> con。 如何按timeStarted升序sorting,然后按timeEnded ? 任何人都可以帮忙吗? 我知道在C ++中使用genericsalgorithm和重载操作符<,但我是Java新手。

可以使ActiveAlarm实现Comparable<ActiveAlarm>或在一个单独的类中实现Comparator<ActiveAlarm> 。 然后打电话:

 Collections.sort(list); 

要么

 Collections.sort(list, comparator); 

一般来说,如果有一个单一的“自然”sorting顺序,实现Comparable<T>是一个好主意,否则(如果你碰巧想按照特定的顺序sorting,但也可能同样容易地要一个不同的顺序)实现Comparator<T> 。 这种特殊的情况可能会发生,说实话…但我可能坚持更灵活的Comparator<T>选项。

编辑:示例实现:

 public class AlarmByTimesComparer implements Comparator<ActiveAlarm> { @Override public int compare(ActiveAlarm x, ActiveAlarm y) { // TODO: Handle null x or y values int startComparison = compare(x.timeStarted, y.timeStarted); return startComparison != 0 ? startComparison : compare(x.timeEnded, y.timeEnded); } // I don't know why this isn't in Long... private static int compare(long a, long b) { return a < b ? -1 : a > b ? 1 : 0; } } 

使用Comparator

例如:

 class Score { private String name; private List<Integer> scores; // +accessor methods } 

  Collections.sort(scores, new Comparator<Score>() { public int compare(Score o1, Score o2) { return o2.getScores().get(0).compareTo(o1.getScores().get(0)); } }); 

我们可以通过以下两种方式之一对列表进行sorting:

1.使用比较器 :当需要在多个地方使用sorting逻辑如果你想在一个地方使用sorting逻辑,那么你可以写一个匿名的内部类如下,否则提取比较器并在多个地方使用

  Collections.sort(arrayList, new Comparator<ActiveAlarm>() { public int compare(ActiveAlarm o1, ActiveAlarm o2) { //Sorts by 'TimeStarted' property return o1.getTimeStarted()<o2.getTimeStarted()?-1:o1.getTimeStarted()>o2.getTimeStarted()?1:doSecodaryOrderSort(o1,o2); } //If 'TimeStarted' property is equal sorts by 'TimeEnded' property public int doSecodaryOrderSort(ActiveAlarm o1,ActiveAlarm o2) { return o1.getTimeEnded()<o2.getTimeEnded()?-1:o1.getTimeEnded()>o2.getTimeEnded()?1:0; } }); 

如果我们可以使用“Long”而不是“long”,我们可以对这些属性进行空值检查。

2.使用Comparable(自然sorting) :如果sortingalgorithm总是坚持一个属性:编写一个实现“Comparable”的类并覆盖下面定义的“compareTo”方法

 class ActiveAlarm implements Comparable<ActiveAlarm>{ public long timeStarted; public long timeEnded; private String name = ""; private String description = ""; private String event; private boolean live = false; public ActiveAlarm(long timeStarted,long timeEnded) { this.timeStarted=timeStarted; this.timeEnded=timeEnded; } public long getTimeStarted() { return timeStarted; } public long getTimeEnded() { return timeEnded; } public int compareTo(ActiveAlarm o) { return timeStarted<o.getTimeStarted()?-1:timeStarted>o.getTimeStarted()?1:doSecodaryOrderSort(o); } public int doSecodaryOrderSort(ActiveAlarm o) { return timeEnded<o.getTimeEnded()?-1:timeEnded>o.getTimeEnded()?1:0; } 

}

调用sorting方法根据自然sorting进行sorting

 Collections.sort(list); 

JAVA 8及以上答案(使用Lambdaexpression式)

在Java 8中,引入了Lambdaexpression式,使其更加简单! 而不是创build一个Comparator()对象的所有脚手架,你可以简化它,如下所示:(以你的对象为例)

 Collections.sort(list, (ActiveAlarm a1, ActiveAlarm a2) -> a1.timeStarted-a2.timeStarted); 

甚至更短:

 Collections.sort(list, Comparator.comparingInt(ActiveAlarm ::getterMethod)); 

这一个陈述相当于以下内容:

 Collections.sort(list, new Comparator<ActiveAlarm>() { @Override public int compare(ActiveAlarm a1, ActiveAlarm a2) { return a1.timeStarted - a2.timeStarted; } }); 

将Lambdaexpression式看作只需要您input代码的相关部分:方法签名和返回的内容。

你的问题的另一部分是如何比较多个领域。 要使用Lambdaexpression式来执行此操作,可以使用.thenComparing()函数将两个比较有效地合并为一个:

 Collections.sort(list, (ActiveAlarm a1, ActiveAlarm a2) -> a1.timeStarted-a2.timeStarted .thenComparing ((ActiveAlarm a1, ActiveAlarm a2) -> a1.timeEnded-a2.timeEnded) ); 

上面的代码将首先按timeStarted对列表进行timeStarted ,然后按timeEnded (对于具有相同timeStartedlogging)进行timeStarted

最后一个注意事项:比较“长”或“整数”原语很容易,你可以从另一个中减去一个。 如果您正在比较对象(“长”或“string”),我build议您使用它们的内置比较。 例:

 Collections.sort(list, (ActiveAlarm a1, ActiveAlarm a2) -> a1.name.compareTo(a2.name) ); 

编辑:感谢卢卡斯埃德指向我.thenComparing()函数。

 public class ActiveAlarm implements Comparable<ActiveAlarm> { public long timeStarted; public long timeEnded; private String name = ""; private String description = ""; private String event; private boolean live = false; public int compareTo(ActiveAlarm a) { if ( this.timeStarted > a.timeStarted ) return 1; else if ( this.timeStarted < a.timeStarted ) return -1; else { if ( this.timeEnded > a.timeEnded ) return 1; else return -1; } } 

这应该给你一个粗略的想法。 一旦完成,您可以调用列表上的Collections.sort()

在Java中,你需要使用静态的Collections.sort方法。 这里是一个CompanyRole对象列表的例子,首先按开始,然后按顺序sorting。 你可以很容易地适应你自己的对象。

 private static void order(List<TextComponent> roles) { Collections.sort(roles, new Comparator() { public int compare(Object o1, Object o2) { int x1 = ((CompanyRole) o1).getBegin(); int x2 = ((CompanyRole) o2).getBegin(); if (x1 != x2) { return x1 - x2; } else { int y1 = ((CompanyRole) o1).getEnd(); int y2 = ((CompanyRole) o2).getEnd(); return y2 - y1; } } }); } 

该列performance在将被sorting:)

番石榴的比较链:

 Collections.sort(list, new Comparator<ActiveAlarm>(){ @Override public int compare(ActiveAlarm a1, ActiveAlarm a2) { return ComparisonChain.start() .compare(a1.timestarted, a2.timestarted) //... .compare(a1.timeEnded, a1.timeEnded).result(); }}); 

从Java8开始,使用ComparatorLambda expressions的组合,可以完成更清晰的工作

例如:

 class Student{ private String name; private List<Score> scores; // +accessor methods } class Score { private int grade; // +accessor methods } 

  Collections.sort(student.getScores(), Comparator.comparing(Score::getGrade); 

您可以调用Collections.sort()并传入需要编写的比较器来比较对象的不同属性。

您可以使用Collections.sort并传递您自己的Comparator<ActiveAlarm>

如上所述,您可以按照

  • 使您的对象实现Comparable
  • 或者将Comparator传递给Collections.sort

如果两者兼而有之, Comparable将被忽略, Comparator将被使用。 这有助于值对象具有自己的逻辑Comparable ,这对于您的值对象来说是最合理的,而每个用例都有其自己的实现。