利用反射实现自定义比较器

问题背景

需求:从第三方获取数据列表,传到前台进行展示,目前前台需要可以根据任意字段进行排序(升序和降序),但是第三方接口不支持排序功能,所以需要手动实现数据的排序。

问题分析
方案一:数据入库
  • 将第三方数据存储到数据库中,直接可以根据sql进行排序输出。
  • 缺点:本来就是实时数据,但是从数据库饶了一圈,先将数据写入,再将数据读出,增加了两次的数据库IO
方案二:根据字段进行排序
  • 根据前台上送的字段信息和升降序信息,实现列表的排序功能。
  • 缺点:因为字段不确定,如果针对每个字段都实现一种排序方式,再加上升降序的情况,比如有M个字段,则需要编写2M种排序实现。
  • 优化:可以动态的获取排序字段实现自定义的比较器,这样就和前台传输的字段进行了解耦,而且也增加了扩展性。
解决方案
思路

数据列表的排序主要是针对字段的比较器进行的,那我们的目标就是创建基于自定义字段的比较器,那大小关系的比较必定设计到字段的get方法,由于字段名不定,所以可以通过反射动态的调用字段的get方法。

实现
/**
 * 自定义排序器
 */
public class HighQuelitySeedComp implements Comparator<HighQualitySeed> {
    @Override
    public int compare(HighQualitySeed o1,HighQualitySeed o2) {
    	//降序升降序规则
        String isAsc = o1.getIsAsc();
        //拼接排序字段的get方法
        String firstLetter = o1.getOrderBy().substring(0, 1).toUpperCase();
        String getMethodName = "get" + firstLetter + o1.getOrderBy().substring(1);
        Class<? extends HighQualitySeed> class1 = o1.getClass();
        Method getMethod;
        try {
        	//获取动态字段的get方法
            getMethod = class1.getMethod(getMethodName);
            //分别调用两个对象的get方法,并比较大小
            BigDecimal value1 = (BigDecimal)getMethod.invoke(o1, new Object[] {});
            BigDecimal value2 = (BigDecimal)getMethod.invoke(o2, new Object[] {});
            return "asc".equals(isAsc)? value1.compareTo(value2):value2.compareTo(value1);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return 0;
    }
}
解释

对象属性中并没有isAsc和OrderBy属性,我是在获取数据列表之后,手动将前台上送的值,传入到对象中,便于在比较器中使用;毕竟重写的compare方法签名不支持传输更多的字段。

        //手动排序
        String orderBy = pageDomain.getOrderByColumn();
        String isAsc = pageDomain.getIsAsc();
        if (StringUtils.isNotEmpty(orderBy)) {
            list.forEach(s -> {
                s.setOrderBy(orderBy);
                s.setIsAsc(isAsc);
            });
调用
            list.sort(new HighQuelitySeedComp());
优化空间
  • 因为我是针对于某个具体的对象写的,所以里面的比较类型我是已知的为BigDecimal,后面的比较大小当然也是使用的BigDecimal;所以这里可以动态的获取字段的类型,实现多个数据类型的自定义排序器。
  • 利用反射调用get方式不是很优雅,可以尝试使用PropertyDescriptor进行优化替换。
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值