如何按某些属性对对象列表进行排序

我的课很简单

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

List<ActiveAlarm>骗局。如何按升序排序的 timeStarted,然后按 timeEnded?有人能帮忙吗?我知道在 C + + 中使用通用算法和重载运算符 < ,但我对 Java 是新手。

384777 次浏览

使用 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));
}
});

从 Java8开始,您可以简单地使用 lambda 表达式来表示 Compator 实例。

Collections.sort(scores, (s1, s2) -> { /* compute and return int */ });

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

要么让 ActiveAlarm实现 Comparable<ActiveAlarm>,要么在单独的类中实现 Comparator<ActiveAlarm>,然后调用:

Collections.sort(list);

或者

Collections.sort(list, comparator);

一般来说,如果有一个“自然的”排序顺序,那么实现 Comparable<T>是一个好主意... ... 否则(如果 发生了想要按照特定的顺序排序,但可能同样容易想要不同的顺序) ,那么最好实现 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;
}
}

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

番石榴 比较链:

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();
}});

在 java 中,需要使用静态 Collections.sort方法。下面是一个 CompanyRole 对象列表的示例,首先按开始排序,然后按结束排序。您可以很容易地适应您自己的对象。

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;
}
}
});
}
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()的名单。

我们可以用两种方法对列表进行排序:

1. 使用 Compator : 当需要在多个位置使用排序逻辑时 如果希望在单个位置使用排序逻辑,那么可以按照以下方式编写匿名内部类,或者提取比较器并在多个位置使用它

  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. 使用 Compaable (自然排序) : 如果排序算法总是遵循一个属性: 编写一个类,实现下面定义的“ Compaable”并重写“ 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;
}

}

调用基于自然排序的排序方法

Collections.sort(list);

正如前面提到的,你可以通过以下方式进行排序:

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

如果同时执行这两个操作,则将忽略 Comparable,并使用 Comparator。这有助于使值对象拥有自己的逻辑 Comparable,这对于您的值对象来说是最合理的排序,而每个单独的用例都有自己的实现。

JAVA 8及以上答案(使用 Lambda 表达式)

在 Java8中,引入了 Lambda 表达式使得这更加容易!您可以简化它,而不是使用它的所有脚手架来创建 Compator ()对象: (使用您的对象作为示例)

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()函数有效地将两个比较合并为一个:

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) );

编辑: 感谢卢卡斯埃德尔指出我的 .thenComparing()功能。

由于 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);

在 java8 + 中,这可以写成如下单行:

collectionObjec.sort(comparator_lamda)comparator.comparing(CollectionType::getterOfProperty)

密码:

ListOfActiveAlarmObj.sort((a,b->a.getTimeStarted().compareTo(b.getTimeStarted())))
 

或者

ListOfActiveAlarmObj.sort(Comparator.comparing(ActiveAlarm::getTimeStarted))

使用 数据流 API的 Java-8解决方案:

timeStartedtimeEndedpublic时(如要求中所提到的) ,因此不(需要)使用 public吸气剂方法:

List<ActiveAlarm> sorted =
list.stream()
.sorted(Comparator.comparingLong((ActiveAlarm alarm) -> alarm.timeStarted)
.thenComparingLong((ActiveAlarm alarm) -> alarm.timeEnded))
.collect(Collectors.toList());

timeStartedtimeEnded具有 public吸气剂方法时:

List<ActiveAlarm> sorted =
list.stream()
.sorted(Comparator.comparingLong(ActiveAlarm::getTimeStarted)
.thenComparingLong(ActiveAlarm::getTimeEnded))
.collect(Collectors.toList());

如果你想对原来的 list本身进行排序:

timeStartedtimeEndedpublic时(如要求中所提到的) ,因此不(需要)使用 public吸气剂方法:

list.sort(Comparator.comparingLong((ActiveAlarm alarm) -> alarm.timeStarted)
.thenComparingLong((ActiveAlarm alarm) -> alarm.timeEnded));

timeStartedtimeEnded具有 public吸气剂方法时:

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;
}
}

产出:

[Alarm 3, Alarm 2, Alarm 1]

员工 POJO 课程

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;
}
}

员工分类管理员工

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;
}


}

对 Java 中的任何对象列表进行排序的最佳和最简单的方法(Java8及以上版本)。 让我们基于属性“ FruName”对一篮子水果进行排序

水果 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 顺序(按字典顺序)进行排序。 输出如下:

[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 流也可以使用(Java8及以上版本) ,而不是 Collections.sort ()。下面是使用 Java 流的代码

List<Fruit> sortedFruits = basketOfFruits.stream().sorted( (f1, f2)->{return f1.getFruitName().compareTo(f2.getFruitName());}).collect(Collectors.toList());

在这里,列表以与 Collections.sort ()相同的方式排序,但是已排序的项目将存储/收集在另一个列表“ sortedFruits”中。因此,如果我们想要打印列表中已排序的项,我们需要打印“ sortedFruits”而不是“ basketOfFruits”