动态排序POJO类列表:实现跨类通用排序方法
通用动态排序方法实现方案
问题背景
现有两个POJO类:
class Employee { String empId; Date empJoiningDate; BigDecimal empExperience; // 必须补充Getter方法,排序依赖属性值获取 public String getEmpId() { return empId; } public Date getEmpJoiningDate() { return empJoiningDate; } public BigDecimal getEmpExperience() { return empExperience; } } class EmployeeDetails { String empName; String address; BigDecimal contactNo; Date empdob; // 同样需要Getter方法 public String getEmpName() { return empName; } public String getAddress() { return address; } public BigDecimal getContactNo() { return contactNo; } public Date getEmpdob() { return empdob; } }
需要实现通用方法sortbyProperty(List<T> list, String columnName, boolean ascOrder),支持按指定属性名对任意POJO列表排序。原写法stream().sorted(Comparator.comparing(Employee::getEmpId))是硬编码属性,无法动态切换排序字段,因此需要通过反射或Bean工具类实现动态属性获取。
实现方案
方案一:纯Java反射实现
通过反射动态生成属性Getter方法调用逻辑,构建通用比较器:
import java.lang.reflect.Method; import java.util.Comparator; import java.util.List; import java.util.function.Function; import java.util.stream.Collectors; public class SortUtils { @SuppressWarnings("unchecked") public static <T> List<T> sortbyProperty(List<T> list, String columnName, boolean ascOrder) { if (list == null || list.isEmpty() || columnName == null || columnName.isBlank()) { return list; } try { // 构建Getter方法名:属性首字母大写+前缀get String getterName = "get" + columnName.substring(0, 1).toUpperCase() + columnName.substring(1); Class<?> clazz = list.get(0).getClass(); Method getterMethod = clazz.getMethod(getterName); // 动态提取属性值的Function Function<T, Comparable> propertyExtractor = t -> { try { return (Comparable) getterMethod.invoke(t); } catch (Exception e) { throw new RuntimeException("获取属性[" + columnName + "]值失败", e); } }; // 构建比较器,根据参数切换升序/降序 Comparator<T> comparator = Comparator.comparing(propertyExtractor); if (!ascOrder) { comparator = comparator.reversed(); } return list.stream().sorted(comparator).collect(Collectors.toList()); } catch (NoSuchMethodException e) { throw new RuntimeException("属性[" + columnName + "]不存在对应的Getter方法", e); } } }
方案二:借助Apache Commons BeanUtils简化操作
引入第三方工具类避免手动处理反射细节,代码更简洁:
- 先添加Maven依赖(若使用Maven):
<dependency> <groupId>commons-beanutils</groupId> <artifactId>commons-beanutils</artifactId> <version>1.9.4</version> </dependency>
- 实现排序方法:
import org.apache.commons.beanutils.PropertyUtils; import java.util.Comparator; import java.util.List; import java.util.function.Function; import java.util.stream.Collectors; public class SortUtils { @SuppressWarnings("unchecked") public static <T> List<T> sortbyProperty(List<T> list, String columnName, boolean ascOrder) { if (list == null || list.isEmpty() || columnName == null || columnName.isBlank()) { return list; } Function<T, Comparable> propertyExtractor = t -> { try { return (Comparable) PropertyUtils.getProperty(t, columnName); } catch (Exception e) { throw new RuntimeException("获取属性[" + columnName + "]值失败", e); } }; Comparator<T> comparator = Comparator.comparing(propertyExtractor); if (!ascOrder) { comparator = comparator.reversed(); } return list.stream().sorted(comparator).collect(Collectors.toList()); } }
使用示例
// 对Employee列表按empId升序排序 List<Employee> empList = ...; List<Employee> sortedEmpList = SortUtils.sortbyProperty(empList, "empId", true); // 对Employee列表按empExperience降序排序 List<Employee> sortedEmpDesc = SortUtils.sortbyProperty(empList, "empExperience", false); // 对EmployeeDetails列表按empName升序排序 List<EmployeeDetails> detailsList = ...; List<EmployeeDetails> sortedDetails = SortUtils.sortbyProperty(detailsList, "empName", true);
注意事项
- 所有参与排序的POJO属性必须存在对应的Getter方法,否则会抛出方法不存在的异常。
- 排序属性的类型必须实现
Comparable接口(String、Date、BigDecimal均已实现),否则无法进行比较操作。 - 方法做了空值校验,空列表、空属性名会直接返回原列表,避免空指针异常。
内容的提问来源于stack exchange,提问作者ParthPatel
相关产品推荐
相关产品推荐

