文
章
目
录
章
目
录
Java List集合对象元素如何根据多属性排序,也就是执行类似SQL的分组排序?该文章涉及使用多个比较器,每个比较器都能够根据模型对象中的不同字段进行排序。
1.模型类和多个比较器
我们的模型类是具有4个简单字段的Employee。
public class Employee implements Comparable<Employee> {
private Integer id = -1;
private Integer age = -1;
private String firstName = null;
private String lastName = null;
public Employee(Integer id, String fName, String lName, Integer age) {
this.id = id;
this.firstName = fName;
this.lastName = lName;
this.age = age;
}
//Getters and Setters
@Override
public String toString() {
return "\nEmployee [id=" + id + ", age=" + age + ", firstName=" + firstName + ", lastName=" + lastName + "]";
}
}
还有多个比较器分别用于姓、名和年龄字段。
public class FirstNameSorter implements Comparator<Employee>
{
public int compare(Employee o1, Employee o2)
{
return o1.getFirstName().compareTo(o2.getFirstName());
}
}
public class LastNameSorter implements Comparator<Employee>
{
public int compare(Employee o1, Employee o2)
{
return o1.getLastName().compareTo(o2.getLastName());
}
}
public class AgeSorter implements Comparator<Employee>
{
public int compare(Employee o1, Employee o2)
{
return o1.getAge() - o2.getAge();
}
}
2.Java按组排序 – Comparator.thenComparing()
在Java 8中,使用内置的比较器链支持非常容易。您可以通过实现Comparator接口创建独立字段排序器,然后在Collections.sort()方法中将它们链接在一起。
public class MultipleFieldSorter
{
public static void main(String[] args)
{
List<Employee> list = Arrays.asList(new Employee(1, "A", "B", 34),
new Employee(4, "C", "D", 30),
new Employee(3, "B", "A", 31),
new Employee(2, "D", "C", 25));
Collections.sort(list, new FirstNameSorter()
.thenComparing(new LastNameSorter())
.thenComparing(new AgeSorter()));
System.out.println(list);
}
}
程序输出:
[Employee [id=1, age=34, firstName=A, lastName=B],
Employee [id=3, age=31, firstName=B, lastName=A],
Employee [id=4, age=30, firstName=C, lastName=D],
Employee [id=2, age=25, firstName=D, lastName=C]]
3.Java按组排序 – CompareToBuilder
值按它们附加到构建器的顺序进行比较。如果任何比较返回非零结果,那么该值将成为CompareToBuilder.toComparison()返回的结果,随后的比较都将被跳过。
3.1. Apache common Lang3 依赖
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.7</version>
</dependency>
3.2. 修改模型中的compareTo()方法
public class Employee implements Comparable<Employee> {
private Integer id = -1;
private Integer age = -1;
private String firstName = null;
private String lastName = null;
public Employee(Integer id, String fName, String lName, Integer age) {
this.id = id;
this.firstName = fName;
this.lastName = lName;
this.age = age;
}
public int compareTo(Employee o) {
if (o == null) {
return -1;
}
CompareToBuilder buider = new CompareToBuilder();
return buider
.append(this.getFirstName(), o.getFirstName())
.append(this.getLastName(), o.getLastName())
.append(this.getAge(), o.getAge())
.toComparison();
}
//getters and setters
}
3.3. 对列表进行排序
public class MultipleFieldSorter
{
@SuppressWarnings("unchecked")
public static void main(String[] args)
{
List<Employee> list = //list of employees;
Collections.sort(list);
System.out.println(list);
}
}
3.4. Comparator接口中的CompareToBuilder
如果您不想修改Comparable接口,仍然可以利用Comparator接口来使用CompareToBuilder对列表进行排序。
public class MultipleFieldSorter
{
public static void main(String[] args)
{
List<Employee> list = Arrays.asList(new Employee(1, "A", "B", 34),
new Employee(4, "C", "D", 30),
new Employee(3, "B", "A", 31),
new Employee(2, "D", "C", 25));
Collections.sort(list, new Comparator<Employee>()
{
public int compare(Employee empOne, Employee empTwo)
{
return new CompareToBuilder()
.append(empOne.getFirstName(), empTwo.getFirstName())
.append(empOne.getLastName(), empTwo.getLastName())
.append(empOne.getAge(), empTwo.getAge())
.toComparison();
}
});
System.out.println(list); //Sorted list
}
}
4.Java按组排序 – ComparisonChain
类似于Apache Common Lang的CompareToBuilder,Google Guava库提供了有用的ComparisonChain类来对对象列表进行排序。
4.1. Guava 依赖
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>23.0</version>
</dependency>
4.2. ComparisonChain示例
public class MultipleFieldSorter
{
public static void main(String[] args)
{
List<Employee> list = Arrays.asList(new Employee(1, "A", "B", 34),
new Employee(4, "C", "D", 30),
new Employee(3, "B", "A", 31),
new Employee(2, "D", "C", 25));
Collections.sort(list, new Comparator<Employee>()
{
public int compare(Employee empOne, Employee empTwo)
{
return ComparisonChain.start()
.compare(empOne.getFirstName(), empTwo.getFirstName())
.compare(empOne.getLastName(), empTwo.getLastName())
.compare(empOne.getAge(), empTwo.getAge())
.result();
}
});
System.out.println(list);
}
}
5.Java按组排序 – 链式比较器
这是使用多个比较器按多个字段对对象列表进行排序的最基本示例。在这种方法中,创建一个有序的比较器列表,并将其传递给一个方法,该方法迭代比较器并使用每个比较器对当前列表进行排序。
5.1. 分组排序器
public class GroupBySorter implements Comparator<Employee> {
private List<Comparator<Employee>> listComparators;
public GroupBySorter(Comparator<Employee>... comparators) {
this.listComparators = Arrays.asList(comparators);
}
public int compare(Employee empOne, Employee empTwo) {
for (Comparator<Employee> comparator : listComparators) {
int result = comparator.compare(empOne, empTwo);
if (result != 0) {
return result;
}
}
return 0;
}
}
5.2. 在列表上应用按组排序
现在,我们可以使用上面的GroupBySorter来对员工列表进行排序。下面的代码按以下顺序对员工列表进行排序:
- 名字
- 姓氏
- 年龄
public class MultipleFieldSorter
{
@SuppressWarnings("unchecked")
public static void main(String[] args)
{
List<Employee> list = Arrays.asList(
new Employee(1, "A", "B", 34),
new Employee(4, "C", "D", 30),
new Employee(3, "B", "A", 31),
new Employee(2, "D", "C", 25));
Collections.sort(list, new GroupBySorter(new FirstNameSorter(), new LastNameSorter(), new AgeSorter()));
System.out.println(list);
}
}
以上就是Java分组排序多个比较器实现的示例方法,希望对你有帮助。