List 中元素需要排序时,需要比较元素值,当元素是复杂对象时,有时需要根据多个字段进行排序。
package com.example.demo.domain;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.ToString;
@Getter
@ToString
@NoArgsConstructor
public class Employee {
private Long id;
private String name;
public Employee(Long id, String name) {
this.id = id ;
this.name = name;
}
}
先看下基础数据类型的比较:
@Test
public void comparator_test(){
// int 类型的比较结果是 1、0、-1 三者之一。
System.out.println( Integer.compare(2,1)); // 1
System.out.println( Integer.compare(2,2)); // 0
System.out.println( Integer.compare(2,4)); // -1
// String 类型的比较结果是 两个字符串长度的差值,左边小为负,左边大为正。
System.out.println("".compareTo("abc")); // -3
System.out.println("abc".compareTo("")); // 3
System.out.println("abc".compareTo("a")); // 2
System.out.println("ab".compareTo("abc")); // -1
System.out.println("abc".compareTo("abc")); // 0
// 将 String 类型的比较结果规约成 1、0、-1 三者之一。
System.out.println(Integer.compare("".compareTo("abc"),0)); // -1
System.out.println(Integer.compare("abc".compareTo(""),0)); // 1
System.out.println(Integer.compare("abc".compareTo("a"),0)); // 1
System.out.println(Integer.compare("ab".compareTo("abc"),0)); // -1
System.out.println(Integer.compare("abc".compareTo("abc"),0)); // 0
}
看一种多字段比较的方式:
package com.example.demo.domain;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import org.junit.jupiter.api.Test;
class EmployeeTest {
@Test
public void should_sort_employees_with_id_and_name(){
List<Employee> employees = new ArrayList<Employee>(){{
add(new Employee(3L,"name-3"));
add(new Employee(1L,"name-1"));
add(new Employee(2L,"name-2"));
add(new Employee(2L,"name-4"));
add(new Employee(3L,"name-1"));
add(new Employee(1L,"name-6"));
add(new Employee(2L,"name-0"));
add(new Employee(3L,"name-2"));
}};
System.out.println(employees);
employees.sort(new EmployeeComparator());
System.out.println(employees);
}
}
// 假定 id 比较的优先级高于 name。
class EmployeeComparator implements Comparator<Employee>{
@Override
public int compare(Employee o1, Employee o2) {
int idCompareResult = Integer.compare(o1.getId().compareTo(o2.getId()),0);
int nameCompareResult = o1.getName().compareTo(o2.getName());
// 将每个字段的比较结果按优先级加权求和,就是两个对象的比较结果了。
int compareResult = idCompareResult * 10 + nameCompareResult;
// 将最终结果规约成 1、0、-1 三者中的一个。
return Integer.compare(compareResult,0);
}
}
结果:
[Employee(id=3, name=name-3), Employee(id=1, name=name-1), Employee(id=2, name=name-2), Employee(id=2, name=name-4), Employee(id=3, name=name-1), Employee(id=1, name=name-6), Employee(id=2, name=name-0), Employee(id=3, name=name-2)]
[Employee(id=1, name=name-1), Employee(id=1, name=name-6), Employee(id=2, name=name-0), Employee(id=2, name=name-2), Employee(id=2, name=name-4), Employee(id=3, name=name-1), Employee(id=3, name=name-2), Employee(id=3, name=name-3)]