动态对 POJO 类列表进行排序

问题描述 投票:0回答:1

考虑我有两个不同的 POJO 类,如下所示。

class Employee {
    String empId;
    
    Date empJoiningDate;
    BigDecimal empExperience;
}

class EmployeeDetails {
    String empName;
    String address;
    BigDecimal contactNo;
    Date empdob;
}

需要创建通用方法,通过该方法我可以对 Employee 或 EmployeeDetails 进行排序

sortbyProperty(List<T> list, String columnName, boolean ascOrder)

尝试使用以下代码,但无法动态执行。

empList.stream().sorted(Comparator.comparing(Employee::getEmpId())).collect(Collectors.toList())
sorting collections java-8 java-stream
1个回答
0
投票

这实现和使用起来很麻烦:

  • 结果
    Comparator
    将是原始的,除非我们定义
    Class<R>
    参数,其中
    <R extends Comparable<R>>
    (答案结束)。
  • 无论如何都需要额外的
    Class<T>
    参数。
  • 需要反思(再见表现)。
  • 故障仅出现在运行时。

使用 Stream API 和比较器进行排序本身很简单。我们剩下的就是实现比较器。

考虑这个方法:

private <T> List<T> sortByProperty(List<T> list, Class<T> type, String columnName, boolean ascOrder) {
    return list.stream()
        .sorted(dynamicComparator(type, columnName, ascOrder))
        .toList();
}

比较器看起来像这样:

private <T> Comparator dynamicComparator(Class<T> type, String fieldName, boolean ascOrder) {
    final var method = Arrays.stream(type.getMethods())
        .filter(m -> m.getName().equals("get" + capitalize(fieldName))
            || m.getName().equals("is" + capitalize(fieldName)))
        .findFirst()
        .orElseThrow(() -> new IllegalArgumentException("No getter for " + fieldName));

    return (o1, o2) -> {
        try {
            final var left = method.invoke(o1);
            final var right = method.invoke(o2);
            if (left instanceof Comparable comparableLeft && right instanceof Comparable comparableRight) {
                return ascOrder 
                    ? comparableLeft.compareTo(comparableRight)
                    : comparableRight.compareTo(comparableLeft);
            } else {
                throw new IllegalArgumentException(fieldName + " is not comparable");
            }
        } catch (IllegalAccessException | InvocationTargetException e) {
            throw new RuntimeException(e);
        }
    };
}

另外,这是需要的:

private String capitalize(String string) {
    return string.substring(0, 1).toUpperCase() + string.substring(1);
}

带有附加

Class<R>
参数的比较器大致如下(未经测试):

private <T, R extends Comparable<R>> Comparator<T> dynamicComparator(Class<T> type, String fieldName, Class<R> columnType, boolean ascOrder) {
    return (o1, o2) -> {
        try {
            final R left = (R) method.invoke(o1);
            final R right = (R) method.invoke(o2);
            return ascOrder ? left.compareTo(right) : right.compareTo(left);
        } catch (ClassCastException e) {
            throw new IllegalArgumentException(fieldName + " is not comparable");
        } catch (InvocationTargetException | IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    };
}
© www.soinside.com 2019 - 2024. All rights reserved.