[英]How to sort List of objects by some property
我有简单的 class
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
升序排序,然后按timeEnded
升序排序? 有人可以帮忙吗? 我知道 C++ 有通用算法和重载运算符 <,但我是 Java 的新手。
使ActiveAlarm
实现Comparable<ActiveAlarm>
或在单独的 class 中实现Comparator<ActiveAlarm>
。 然后调用:
Collections.sort(list);
或者
Collections.sort(list, comparator);
一般来说,如果有一个单一的“自然”排序顺序,那么实现Comparable<T>
是一个好主意......否则(如果您碰巧想要按特定顺序排序,但可能同样容易想要一个不同的顺序)它会更好实现Comparator<T>
。 这种特殊情况可能会 go 无论如何,老实说......但我可能会坚持使用更灵活的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) {
// compare two instance of `Score` and return `int` as result.
return o2.getScores().get(0).compareTo(o1.getScores().get(0));
}
});
从 Java 8 开始,您可以简单地使用 lambda 表达式来表示 Comparator 实例。
Collections.sort(scores, (s1, s2) -> { /* compute and return int */ });
JAVA 8 及以上答案(使用 Lambda 表达式)
In Java 8, Lambda expressions were introduced to make this even easier, Instead of creating a Comparator() object with all of it's scaffolding: you can simplify it as follows: (Using your object as an example)
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;
}
});
将 Lambda 表达式视为只需要您输入代码的相关部分:方法签名和返回的内容。
您问题的另一部分是如何与多个字段进行比较。 要使用 Lambda 表达式做到这一点,您可以使用.thenComparing()
function 有效地将两个比较合并为一个:
Collections.sort(list, (ActiveAlarm a1, ActiveAlarm a2) -> a1.timeStarted-a2.timeStarted
.thenComparing ((ActiveAlarm a1, ActiveAlarm a2) -> a1.timeEnded-a2.timeEnded)
);
上面的代码将首先按timeStarted
排序列表,然后按timeEnded
(对于那些具有相同timeStarted
的记录)。
最后一点:比较“long”或“int”原语很容易,你可以从另一个中减去一个。 如果您要比较对象(“Long”或“String”),我建议您使用它们的内置比较。 例子:
Collections.sort(list, (ActiveAlarm a1, ActiveAlarm a2) -> a1.name.compareTo(a2.name) );
编辑:感谢 Lukas Eder 将我指向.thenComparing()
function。
我们可以通过以下两种方式之一对列表进行排序:
1. 使用比较器:当需要在多个地方使用排序逻辑如果你想在一个地方使用排序逻辑,那么你可以写一个匿名内部 class 如下,或者提取比较器并在多个地方使用它
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”,我们可以让 null 检查属性。
2. 使用 Comparable(自然排序) :如果排序算法始终坚持一个属性:编写一个 class 实现 '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;
}
}
调用 sort 方法进行基于自然排序的排序
Collections.sort(list);
在 java8+ 中,这可以写成一行,如下所示:
collectionObjec.sort(comparator_lamda)
或comparator.comparing(CollectionType::getterOfProperty)
代码:
ListOfActiveAlarmObj.sort((a,b->a.getTimeStarted().compareTo(b.getTimeStarted())))
或者
ListOfActiveAlarmObj.sort(Comparator.comparing(ActiveAlarm::getTimeStarted))
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()
。
由于 Java8,这可以使用Comparator
和Lambda 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);
Guava 的比较链:
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();
}});
您可以使用Collections.sort
并传递您自己的Comparator<ActiveAlarm>
在 java 中,您需要使用 static Collections.sort
方法。 这是 CompanyRole 对象列表的示例,首先按开始排序,然后按结束排序。 您可以轻松适应自己的 object。
private static void order(List<TextComponent> roles) {
Collections.sort(roles, new Comparator() {
@Override
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;
}
}
});
}
A.当timeStarted
和timeEnded
是public
的(如要求中所述)并且因此不(需要)具有public
getter 方法时:
List<ActiveAlarm> sorted =
list.stream()
.sorted(Comparator.comparingLong((ActiveAlarm alarm) -> alarm.timeStarted)
.thenComparingLong((ActiveAlarm alarm) -> alarm.timeEnded))
.collect(Collectors.toList());
B.当timeStarted
和timeEnded
有public
getter 方法时:
List<ActiveAlarm> sorted =
list.stream()
.sorted(Comparator.comparingLong(ActiveAlarm::getTimeStarted)
.thenComparingLong(ActiveAlarm::getTimeEnded))
.collect(Collectors.toList());
list
本身进行排序: A.当timeStarted
和timeEnded
是public
的(如要求中所述)并且因此不(需要)具有public
getter 方法时:
list.sort(Comparator.comparingLong((ActiveAlarm alarm) -> alarm.timeStarted)
.thenComparingLong((ActiveAlarm alarm) -> alarm.timeEnded));
B.当timeStarted
和timeEnded
有public
getter 方法时:
list.sort(Comparator.comparingLong(ActiveAlarm::getTimeStarted)
.thenComparingLong(ActiveAlarm::getTimeEnded));
我们可以使用Comparator.comparing()
方法根据对象的属性对列表进行排序。
class SortTest{
public static void main(String[] args) {
ArrayList<ActiveAlarm> activeAlarms = new ArrayList<>(){{
add(new ActiveAlarm("Alarm 1", 5, 10));
add(new ActiveAlarm("Alarm 2", 2, 12));
add(new ActiveAlarm("Alarm 3", 0, 8));
}};
/* I sort the arraylist here using the getter methods */
activeAlarms.sort(Comparator.comparing(ActiveAlarm::getTimeStarted)
.thenComparing(ActiveAlarm::getTimeEnded));
System.out.println(activeAlarms);
}
}
请注意,在执行此操作之前,您必须至少定义要作为排序依据的属性的 getter 方法。
public class ActiveAlarm {
public long timeStarted;
public long timeEnded;
private String name = "";
private String description = "";
private String event;
private boolean live = false;
public ActiveAlarm(String name, long timeStarted, long timeEnded) {
this.name = name;
this.timeStarted = timeStarted;
this.timeEnded = timeEnded;
}
public long getTimeStarted() {
return timeStarted;
}
public long getTimeEnded() {
return timeEnded;
}
@Override
public String toString() {
return name;
}
}
Output:
[Alarm 3, Alarm 2, Alarm 1]
如前所述,您可以按以下方式排序:
Comparable
Comparator
器传递给Collections.sort
如果两者都做,则Comparable
将被忽略,而Comparator
将被使用。 这有助于值对象有自己的逻辑Comparable
,这是对您的值 object 最合理的排序,而每个单独的用例都有自己的实现。
您可以调用 Collections.sort() 并传入您需要编写的比较器来比较 object 的不同属性。
员工 POJO Class
package in.ac.adit.oop.sort;
public class Employee {
private int id;
private String name;
private String department;
public int getId() {
return id;
}
public Employee() {
super();
}
public Employee(int id, String name, String department) {
super();
this.id = id;
this.name = name;
this.department = department;
}
@Override
public String toString() {
return "Employee [id=" + id + ", name=" + name + ", department=" + department + "]";
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDepartment() {
return department;
}
public void setDepartment(String department) {
this.department = department;
}
}
员工 Class 管理员工
package in.ac.adit.oop.sort;
import java.util.ArrayList;
import java.util.List;
public class Example {
public static void main(String[] args) {
/*
* Create 10 Employee Object
*/
Employee emp1 = new Employee(1, "Nayan", "IT");
Employee emp2 = new Employee(2, "Siddarth", "CP");
Employee emp3 = new Employee(3, "Samarth", "AE");
Employee emp4 = new Employee(4, "Bhavesh", "CV");
Employee emp5 = new Employee(5, "Sam", "FT");
Employee emp6 = new Employee(6, "Keyur", "IT");
Employee emp7 = new Employee(7, "Bala", "ME");
Employee emp8 = new Employee(8, "Mitul", "ME");
Employee emp9 = new Employee(9, "Kamlesh", "EE");
Employee emp10 = new Employee(10, "Piyush", "EE");
/*
* List of Employee Object
*/
List<Employee> employeeList = new ArrayList<Employee>();
employeeList.add(emp1);
employeeList.add(emp2);
employeeList.add(emp3);
employeeList.add(emp4);
employeeList.add(emp5);
employeeList.add(emp6);
employeeList.add(emp7);
employeeList.add(emp8);
employeeList.add(emp9);
employeeList.add(emp10);
CustomObjectSort customObjectSort = new CustomObjectSort();
List<Employee> sortByDepartment = customObjectSort.sortByDepartment(employeeList);
/*
* Sorted By Department
*/
for (Employee employee : sortByDepartment) {
System.out.println(employee);
}
/*
* Sorted By Name
*/
List<Employee> sortByName = customObjectSort.sortByName(employeeList);
for (Employee employee : sortByName) {
System.out.println(employee);
}
/*
* Sorted By Id
*/
List<Employee> sortById = customObjectSort.sortById(employeeList);
for (Employee employee : sortById) {
System.out.println(employee);
}
}
}
自定义排序
package in.ac.adit.oop.sort;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class CustomObjectSort {
public List<Employee> sortByName(List<Employee> employeeList) {
Collections.sort(employeeList, new Comparator<Employee>() {
@Override
public int compare(Employee employee1, Employee employee2) {
return employee1.getName().compareTo(employee2.getName());
}
});
return employeeList;
}
public List<Employee> sortByDepartment(List<Employee> employeeList) {
Collections.sort(employeeList, new Comparator<Employee>() {
@Override
public int compare(Employee employee1, Employee employee2) {
return employee1.getDepartment().compareTo(employee2.getDepartment());
}
});
return employeeList;
}
public List<Employee> sortById(List<Employee> employeeList) {
Collections.sort(employeeList, new Comparator<Employee>() {
@Override
public int compare(Employee employee1, Employee employee2) {
return employee1.getId() - employee2.getId();
}
});
return employeeList;
}
}
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 = new ArrayList<ActiveAlarm>(); Collections.sort(con, (a1, a2) -> a1.timeStarted.compareTo(a2.timeStarted)); Collections.sort(con, (a1, a2) -> a1.timeEnded.compareTo(a2.timeEnded));
对 Java(Java 8 及更高版本)中的任何对象列表进行排序的最佳和最简单的方法。 让我们根据属性“fruitName”对一篮子水果进行排序
水果POJO:
class Fruit
{
int price;
String fruitName;
public Fruit(int price, String fruitName) {
super();
this.price = price;
this.fruitName = fruitName;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
public String getFruitName() {
return fruitName;
}
public void setFruitName(String fruitName) {
this.fruitName = fruitName;
}
@Override
public String toString() {
return "Fruits [price=" + price + ", fruitName=" + fruitName + "]";
}
}
现在让我们将水果添加到列表中,然后对其进行排序
List<Fruit> basketOfFruits = new ArrayList<>();
basketOfFruits.add(new Fruit(123, "oranges"));
basketOfFruits.add(new Fruit(45, "nectarine"));
basketOfFruits.add(new Fruit(369, "blueberries"));
basketOfFruits.add(new Fruit(248, "apple"));
basketOfFruits.add(new Fruit(968, "peaches"));
basketOfFruits.add(new Fruit(436, "grapes"));
basketOfFruits.add(new Fruit(596, "figs"));
//sorting by the property fruitName
Collections.sort(basketOfFruits, (f1, f2)->{return f1.getFruitName().compareTo(f2.getFruitName());});
您现在可以打印列表(即 basketOfFruits),列表中的水果将按 ASCENDING 顺序(按字典顺序)排序。 output 看起来像这样:
[Fruits [price=248, fruitName=apple], Fruits [price=369, fruitName=blueberries], Fruits [price=596, fruitName=figs], Fruits [price=436, fruitName=grapes], Fruits [price=45, fruitName=nectarine], Fruits [price=123, fruitName=oranges], Fruits [price=968, fruitName=peaches]]
也可以使用 Java 流代替 Collections.sort()(Java 8 及更高版本)。 以下是使用 Java 流的代码
List<Fruit> sortedFruits = basketOfFruits.stream().sorted( (f1, f2)->{return f1.getFruitName().compareTo(f2.getFruitName());}).collect(Collectors.toList());
这里列表的排序方式与 Collections.sort() 相同,但排序后的项目将存储/收集在另一个列表“sortedFruits”中。 所以,如果我们想打印列表的排序项,在这种情况下我们需要打印“sortedFruits”而不是“basketOfFruits”
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.