一、前言

Java的比较器是用来对List集合进行排序用的,分为内部比较器和外部比较器两类

内部比较器:被排序的类要 implements Comparable 类,并实现compareTo方法。

外部比较器:需要实现一个implements  Comparator的比较器,实现compare方法,并在sort方法中将该比较器当参数传入。

(具体实现,网络上有很多资料,此处不再赘述)

二、发现问题

外部比较器虽然相比内部比较器 实现了解耦,代码侵入小,但是两者都不能摆脱同一个麻烦的问题:

那就是对每个待排序的对象,均需单独实现一个比较器类。如果项目中有很多类都需要排序,那就需要重复劳动,写很多个比较器类了。

本文的目的,即通过泛型和反射机制的应用,来设计实现一个通用的外部比较器。该比较器对任何待排序的对象均能适用,减少低级的重复劳动。

三、实现思路

四、实现

话不多说,直接贴代码:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Method;
import java.text.Collator;
import java.util.Comparator;

/**
 * @Description:
指定需根据某字段排序的方法名,进行排序,返回类型自动判断,目前支持Integer String
 * @Author: wangzhen3
 * @CreationTime: 2018/5/29 15:02
 * @ModifiedBy:
 
*/
public class CompareByFunctionName<T> implements Comparator<T> {
    private static
final Logger logger = LoggerFactory.getLogger(CompareByFunctionName.class);
    /**
     *
需比较字段的方法名 如 getStatus
     */
   
private String functionName = "";
    /**
     *
是否倒序
    
*/
   
private Boolean invert = false;

public CompareByFunctionName(String functionName){
        this.functionName = functionName;
        this.invert = false;
    }

public CompareByFunctionName(String functionName, Boolean invert){
        this.functionName = functionName;
        this.invert = invert;
    }
    @Override
    public int compare(T o1, T o2) {
        Object ret1;
        Object ret2;
        Method method;
        try {
            method =  o1.getClass().getMethod(functionName);
            ret1 =
method.invoke(o1);
            ret2 =
method.invoke(o2);
           if(ret1 instanceof Integer){
               return !invert? (Integer)ret1 - (Integer)ret2 :
                       (Integer)ret2 -
(Integer)ret1;
           }else if(ret1 instanceof String){
               return !invert? Collator.getInstance(java.util.Locale.CHINA).compare(ret1,ret2) :
                       Collator.getInstance(java.util.Locale.CHINA).compare(ret2,ret1);
           }else{
               //直接toString 比较
               return !invert? Collator.getInstance(java.util.Locale.CHINA).compare(ret1.toString(),ret2.toString())
:
                       Collator.getInstance(java.util.Locale.CHINA).compare(ret2.toString(),ret1.toString());
           }

}catch (Exception e){
            logger.error(e.getMessage());
        }
        logger.error("比较失败,o1={},o2={}",o1.toString(),o2.toString());
        return 0;
    }
}

关键步骤说明:

1)java反射机制中的Field 和 Method 方法,网上有很多博客介绍,此处不赘述。

2)functionName 必须为public方法,不然无访问权限。

或许你会有疑问,为什么此处反射是使用Method获得数据值 而不直接用字段Field来获取数据值,原因是字段一般被声明为private,所以通过Field一般无访问权限,无法取出数据,而Method ,比如status 字段的getStatus方法,通常是public ,所以能取出数据。

3)当然,functionName 是可以换成 字段名称fieldName 的,只需要新增转换逻辑,根据java的驼峰式命名约定,把fieldName 转换为functionName 即可

4)Collator.getInstance(java.util.Locale.CHINA)
.compare()

为了实现中文字符串排序功能

五、实际应用

项目中使用示例:

根据字段status对List<MonitorAlarmData>  进行倒序排列,使status=1的排在开头,status=-1的排在末尾

public class MonitorAlarmData {

    private String id; //problem id

    private Integer status;//当前状态 -1 已忽略; 0 OK; 1 problem;

    public String getId() {
        return id;
    }     public void setId(String id) {
        this.id = id;
    }     public Integer getStatus() {
        return status;
    }     public void setStatus(Integer status) {
        this.status = status;
    }
   }
List<MonitorAlarmData> monitorAlarmDataList = new ArrayList<>();
//省略代码,往monitorAlarmDataList 中添加数据
//排序
monitorAlarmDataList.sort(new CompareByFunctionName("getStatus",true));

java-基于泛型和反射机制的通用比较器实现的更多相关文章

  1. java的泛型与反射机制

    什么是泛型? 泛型,即“参数化类型”.顾名思义,就是将类型由原来的具体的类型参数化,类似于方法中的变量参数,此时类型也定义成参数形式(可以称之为类型形参),然后在使用/调用时传入具体的类型(类型实参) ...

  2. Java基础系列 - 泛型和反射机制

    package com.test5; import java.lang.reflect.Field; import java.lang.reflect.Method; /** * Java泛型和反射机 ...

  3. JAVA动态性之一一反射机制reflection

    package com.bjsxt.reflection.test.bean; public class User { private int id; private int age; private ...

  4. Java 核心类库之反射机制

    1:什么是反射机制? 2:反射机制它可以做什么呢? 3:反射机制对应的API又是什么? 1):通过反射机制来获取一个对象的全限定名称(完整包名),和类名: 2):实例化Class对象 3):获取对象的 ...

  5. Java基于注解和反射导入导出Excel

    代码地址如下:http://www.demodashi.com/demo/11995.html 1. 构建项目 使用Spring Boot快速构建一个Web工程,并导入与操作Excel相关的POI包以 ...

  6. 利用JAVA反射机制设计通用的DAO

    利用JAVA反射机制设计一个通用的DAO 反射机制 反射机制指的是程序在运行时能够获取自身的信息.在java中,只要给定类的名字,    那么就可以通过反射机制来获得类的所有信息. 反射机制创建类对象 ...

  7. 关于Java中泛型、反射和注解的扫盲篇

    泛型 泛型概念   泛型是在JDK1.5之后引入的,旨在让我们写出更加通用化,更加灵活的代码.通用化的手段在于让数据类型变得参数化,定义泛型时,对应的数据类型是不确定的,泛型方法被调用时,会指定具体类 ...

  8. java的RTTI和反射机制

    RTTI,即Run-Time Type Identification,运行时类型识别.RTTI能在运行时就能够自动识别每个编译时已知的类型. 很多时候需要进行向上转型,比如Base类派生出Derive ...

  9. java.lang.Class<T> -- 反射机制

    1反射机制是什么 反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为jav ...

随机推荐

  1. AFNetworking 2.0教程

    在iOS 7中,Apple更新了iOS中的网络基础架构,新推出的网络基础架构是NSURLSession(原来的网络基础架构NSURLConnection). iOS开发中往往会涉及网络数据处理,像其他 ...

  2. 【SDOI2009】SuperGCD

    [题目链接] 点击打开链接 [算法] 1.关于求最大公约数的算法 若使用辗转相除法,那么显然会超时 不妨这样思考 : 要求gcd(a,b), 若a为偶数,b为偶数,则gcd(a,b) = 2 * gc ...

  3. Spring注解的(List&Map)特殊注入功能

    一.先看一个示例演示:spring注解的一个特殊的注入功能. 首先,是定义一个接口,3个实现类. public interface GreetService { public String sayHe ...

  4. ASP.NET Core:WebAppCoreApi

    ylbtech-ASP.NET Core:WebAppCoreApi 1.返回顶部 1. 2. 3.           4. 2. Controllers返回顶部 1.ValuesControlle ...

  5. POJ2366【二分】

    题意: 给两个序列,问两个序列中是否有两个数加起来=1e4: 思路: 直接先排序好b序列,然后枚举a序列,二分查找b序列就好了: 贴一发挫code-. //#include <bits/stdc ...

  6. 一道简单的 Java 笔试题,但值得很多人反思!

    前言 面试别人,对我来说是一件新奇事,以前都是别人面试我.我清楚地知道,我在的地域与公司,难以吸引到中国的一流软件人才.所以,我特地调低了期望,很少问什么深入的技术问题,只问一些广泛的.基础的.我只要 ...

  7. IT兄弟连 JavaWeb教程 Servlet表单数据

    很多情况下,需要传递一些信息,从浏览器到Web服务器,最终到后台程序.浏览器使用两种方法可将这些信息传递到Web服务器,分别为GET方法和POST方法. 1.GET方法 GET 方法向页面请求发送已编 ...

  8. 第八篇 .NET高级技术之字符串暂存池(缓冲池)

    字符串不可变性,字符串的‘暂存池’两个特性 字符串是引用类型,程序中会存在大量的字符串对象,如果每次都创建一个字符串对象,会比较浪费内存.性能低,因此CLR做了“暂存池”(拘留池,缓冲池,暂存池),在 ...

  9. python之yaml模块和ddt模块

    aml文件是专门用来写配置文件的语言,非常简洁和强大,远比json格式方便. 在PC中新建一个yml/yaml为为缩略名的文件,输入信息见下图 新建一个py文件处理yml文件,直接处理成字典格式 缩进 ...

  10. Hdu 4725 The Shortest Path in Nya Graph (spfa)

    题目链接: Hdu 4725 The Shortest Path in Nya Graph 题目描述: 有n个点,m条边,每经过路i需要wi元.并且每一个点都有自己所在的层.一个点都乡里的层需要花费c ...