You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

动态排序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简化操作

引入第三方工具类避免手动处理反射细节,代码更简洁:

  1. 先添加Maven依赖(若使用Maven):
<dependency>
    <groupId>commons-beanutils</groupId>
    <artifactId>commons-beanutils</artifactId>
    <version>1.9.4</version>
</dependency>
  1. 实现排序方法:
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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 11:01:20