Java封装了一个自适应的单位转换工具类

发布时间:2024年01月12日

目录

前言

1、前期准备

2、实现代码

2.1 方法一:通过map去标记需要转换的 类属性字段

2.2 方法二:配合自定义注解


前言

平时在做项目中,经常会做一些数据书籍,尤其像是数据看板之类,需要从数据库中查询想要的数据,但这些数据的单位往往与需求是不匹配的。

比如,数据库中查询的金额是元,但页面上需要展示万元;

亦或是,数据库中查出的距离是米,业务需要的是千米;

又比如,需要将查出的数据除以100,返回前端做百分比展示。等等。。。。。。

那像这种情况,我们是怎么处理的呢?

很多时候我们拿到的是一个数据集合list,然后去遍历集合获取每个参数,再根据参数的属性去做相关的单位转换处理。然后一直重复做着get set,get set,get set。

像这样:

虽然这种写法不会报错,但是看着重复的get set方法,着实是有点孬。所以就封装了一个单位转换的工具类,请看正文。


1、前期准备

  • 接收数据的实体类:
import lombok.Data;

import java.io.Serializable;
import java.math.BigDecimal;

/**
 * 单位转换Vo
 */
@Data
public class UnitConvertVo implements Serializable {

    private static final long serialVersionUID = 4784820539438132009L;

    /*** 日销售额(千元)*/
    private BigDecimal dailySales;

    /*** 年销售额(万元)*/
    private BigDecimal annualSales;

    /*** 营收占比(百分比)*/
    private BigDecimal percentage;

    /*** 营收占比(千分比)*/
    private BigDecimal perMillage;

    /*** 距离*/
    private BigDecimal distance;

    /*** 重量*/
    private BigDecimal weight;

}
  • 定义单位类型枚举类

/**
 * 单位转换枚举
 */
public enum UnitEnum {

    /*** 千元*/
    THOUSAND_YUAN("1", "千元"),
    /*** 万元*/
    TEN_THOUSAND_YUAN("2", "万元"),
    /*** 百分比*/
    PERCENTAGE("3", "百分比"),
    /*** 千分比*/
    PER_MILLAGE("4", "千分比"),
    /*** 米*/
    METER("5", "米"),
    /*** 千米*/
    KILOMETRE("6", "千米"),
    /*** 千克*/
    KILOGRAM("8", "千克"),
    /*** 吨*/
    TON("9", "吨");

    private final String code;

    private final String name;

    UnitEnum(String code, String name) {
        this.code = code;
        this.name = name;
    }

    public String getCode() {
        return code;
    }

    public String getName() {
        return name;
    }
}

2、实现代码

提供两种方法实现:

2.1 方法一:通过map去标记需要转换的 类属性字段

思路

1.通过反射取出字段
2.配合传入的转换标记Map,匹配哪些字段需要转换
3.然后从Map中取出相关字段的具体操作有哪些,然后执行转换
4.重新赋值

核心工具类:

import com.test.java.base.UnitEnum;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;
import java.util.Map;

/**
 * 单位转换工具类
 */
@Slf4j
public class UnitConvertUtil {

    /**
     * 方法一:通过反射,获取标识map进行转换
     */
    public static <T> void unitMapConvert(List<T> list, Map<String, UnitEnum> propertyMap) {
        for (T t : list) {
            Field[] declaredFields = t.getClass().getDeclaredFields();
            for (Field declaredField : declaredFields) {
                // 匹配map里的字段属性和转换操作
                if (propertyMap.keySet().stream().anyMatch(x -> x.equals(declaredField.getName()))) {
                    try {
                        declaredField.setAccessible(true);
                        Object object = declaredField.get(t);
                        UnitEnum unitEnum = propertyMap.get(declaredField.getName());
                        if (object != null) {// 若匹配上,则执行对应的转换操作(加减乘除)
                            // 元 → 千元
                            if (unitEnum.equals(UnitEnum.THOUSAND_YUAN)) {
                                BigDecimal bigDecimal = ((BigDecimal) object).divide(new BigDecimal("1000"), 2, RoundingMode.HALF_UP);
                                declaredField.set(t, bigDecimal);
                            }
                            // 元 → 万元
                            if (unitEnum.equals(UnitEnum.TEN_THOUSAND_YUAN)) {
                                BigDecimal bigDecimal = ((BigDecimal) object).divide(new BigDecimal("10000"), 2, RoundingMode.HALF_UP);
                                declaredField.set(t, bigDecimal);
                            }
                            // 百分比
                            if (unitEnum.equals(UnitEnum.PERCENTAGE)) {
                                BigDecimal bigDecimal = ((BigDecimal) object).multiply(new BigDecimal("100")).setScale(2, RoundingMode.HALF_UP);
                                declaredField.set(t, bigDecimal);
                            }
                            // 千分比
                            if (unitEnum.equals(UnitEnum.PER_MILLAGE)) {
                                BigDecimal bigDecimal = ((BigDecimal) object).multiply(new BigDecimal("1000")).setScale(2, RoundingMode.HALF_UP);
                                declaredField.set(t, bigDecimal);
                            }
                            // 千米 → 米
                            if (unitEnum.equals(UnitEnum.METER)) {
                                BigDecimal bigDecimal = ((BigDecimal) object).multiply(new BigDecimal("1000")).setScale(2, RoundingMode.HALF_UP);
                                declaredField.set(t, bigDecimal);
                            }
                            // 米 → 千米
                            if (unitEnum.equals(UnitEnum.KILOMETRE)) {
                                BigDecimal bigDecimal = ((BigDecimal) object).divide(new BigDecimal("1000"), 2, RoundingMode.HALF_UP);
                                declaredField.set(t, bigDecimal);
                            }
                            // 吨 → 千克
                            if (unitEnum.equals(UnitEnum.KILOGRAM)) {
                                BigDecimal bigDecimal = ((BigDecimal) object).multiply(new BigDecimal("1000")).setScale(2, RoundingMode.HALF_UP);
                                declaredField.set(t, bigDecimal);
                            }
                            // 千克 → 吨
                            if (unitEnum.equals(UnitEnum.TON)) {
                                BigDecimal bigDecimal = ((BigDecimal) object).divide(new BigDecimal("1000"), 2, RoundingMode.HALF_UP);
                                declaredField.set(t, bigDecimal);
                            }
                        }
                    } catch (Exception e) {
                        log.error("单位转换失败,{}", e.getMessage());
                    }
                }
            }
        }
    }


}

写个测试main方法:

    public static void main(String[] args) {

        // 创建测试数据
        UnitConvertVo vo = new UnitConvertVo();
        vo.setDailySales(new BigDecimal("23600.53"));
        vo.setAnnualSales(new BigDecimal("368624.24"));
        vo.setPercentage(new BigDecimal("0.2361"));
        vo.setPerMillage(new BigDecimal("0.536285"));
        vo.setDistance(new BigDecimal("8568.54"));// 米 → 千米
        vo.setWeight(new BigDecimal("35.62638"));// 吨 → 千克

        List<UnitConvertVo> list1 = new ArrayList<>();
        list1.add(vo);

        // 测试方法一:
        Map<String, UnitEnum> map = new HashMap<>();
        map.put("dailySales", UnitEnum.THOUSAND_YUAN);
        map.put("annualSales", UnitEnum.TEN_THOUSAND_YUAN);
        map.put("percentage", UnitEnum.PERCENTAGE);
        map.put("perMillage", UnitEnum.PER_MILLAGE);
        map.put("distance", UnitEnum.KILOMETRE);
        map.put("weight", UnitEnum.KILOGRAM);
        System.out.println("转换前:" + list1);
        unitMapConvert(list1, map);
        System.out.println("通过map标识转换:" + list1);

    }

转换结果:

2.2 方法二:配合自定义注解

其实第一种方法已经够用了,但是为了调用更加的方便,后期能够更好的拓展,所以配合着自定义注解,优化了一下,直接上代码:

  • 定义自定义注解
package com.test.java.annotation;

import com.test.java.base.UnitEnum;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 单位转换 自定义注解
 */
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface UnitConvert {

    UnitEnum name();

}
  • 在实体类上,使用自定义注解

import com.test.java.annotation.UnitConvert;
import com.test.java.base.UnitEnum;
import lombok.Data;

import java.io.Serializable;
import java.math.BigDecimal;

/**
 * 单位转换Vo
 */
@Data
public class UnitConvertVo implements Serializable {

    private static final long serialVersionUID = 4784820539438132009L;

    /*** 日销售额(千元)*/
    @UnitConvert(name = UnitEnum.THOUSAND_YUAN)
    private BigDecimal dailySales;

    /*** 年销售额(万元)*/
    @UnitConvert(name = UnitEnum.TEN_THOUSAND_YUAN)
    private BigDecimal annualSales;

    /*** 营收占比(百分比)*/
    @UnitConvert(name = UnitEnum.PERCENTAGE)
    private BigDecimal percentage;

    /*** 营收占比(千分比)*/
    @UnitConvert(name = UnitEnum.PER_MILLAGE)
    private BigDecimal perMillage;

    /*** 距离*/
    @UnitConvert(name = UnitEnum.METER)
    private BigDecimal distance;

    /*** 重量*/
    @UnitConvert(name = UnitEnum.TON)
    private BigDecimal weight;

}

配合自定义注解,在刚刚的工具类里又封装了一个方法,反射获取属性字段,解析注解,做对应转换操作。

import com.test.java.annotation.UnitConvert;
import com.test.java.base.UnitEnum;
import com.test.java.domain.vo.UnitConvertVo;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;

/**
 * 单位转换工具类
 */
@Slf4j
public class UnitConvertUtil {

    /**
     * 方法一:通过反射,获取标识map进行转换
     */
    public static <T> void unitMapConvert(List<T> list, Map<String, UnitEnum> propertyMap) {
        for (T t : list) {
            Field[] declaredFields = t.getClass().getDeclaredFields();
            for (Field declaredField : declaredFields) {
                // 匹配map里的字段属性和转换操作
                if (propertyMap.keySet().stream().anyMatch(x -> x.equals(declaredField.getName()))) {
                    try {
                        declaredField.setAccessible(true);
                        Object object = declaredField.get(t);
                        UnitEnum unitEnum = propertyMap.get(declaredField.getName());
                        if (object != null) {// 若匹配上,则执行对应的转换操作(加减乘除)
                            // 元 → 千元
                            if (unitEnum.equals(UnitEnum.THOUSAND_YUAN)) {
                                BigDecimal bigDecimal = ((BigDecimal) object).divide(new BigDecimal("1000"), 2, RoundingMode.HALF_UP);
                                declaredField.set(t, bigDecimal);
                            }
                            // 元 → 万元
                            if (unitEnum.equals(UnitEnum.TEN_THOUSAND_YUAN)) {
                                BigDecimal bigDecimal = ((BigDecimal) object).divide(new BigDecimal("10000"), 2, RoundingMode.HALF_UP);
                                declaredField.set(t, bigDecimal);
                            }
                            // 百分比
                            if (unitEnum.equals(UnitEnum.PERCENTAGE)) {
                                BigDecimal bigDecimal = ((BigDecimal) object).multiply(new BigDecimal("100")).setScale(2, RoundingMode.HALF_UP);
                                declaredField.set(t, bigDecimal);
                            }
                            // 千分比
                            if (unitEnum.equals(UnitEnum.PER_MILLAGE)) {
                                BigDecimal bigDecimal = ((BigDecimal) object).multiply(new BigDecimal("1000")).setScale(2, RoundingMode.HALF_UP);
                                declaredField.set(t, bigDecimal);
                            }
                            // 千米 → 米
                            if (unitEnum.equals(UnitEnum.METER)) {
                                BigDecimal bigDecimal = ((BigDecimal) object).multiply(new BigDecimal("1000")).setScale(2, RoundingMode.HALF_UP);
                                declaredField.set(t, bigDecimal);
                            }
                            // 米 → 千米
                            if (unitEnum.equals(UnitEnum.KILOMETRE)) {
                                BigDecimal bigDecimal = ((BigDecimal) object).divide(new BigDecimal("1000"), 2, RoundingMode.HALF_UP);
                                declaredField.set(t, bigDecimal);
                            }
                            // 吨 → 千克
                            if (unitEnum.equals(UnitEnum.KILOGRAM)) {
                                BigDecimal bigDecimal = ((BigDecimal) object).multiply(new BigDecimal("1000")).setScale(2, RoundingMode.HALF_UP);
                                declaredField.set(t, bigDecimal);
                            }
                            // 千克 → 吨
                            if (unitEnum.equals(UnitEnum.TON)) {
                                BigDecimal bigDecimal = ((BigDecimal) object).divide(new BigDecimal("1000"), 2, RoundingMode.HALF_UP);
                                declaredField.set(t, bigDecimal);
                            }
                        }
                    } catch (Exception e) {
                        log.error("单位转换失败,{}", e.getMessage());
                    }
                }
            }
        }
    }

    /**
     * 方法二:通过自定义注解 进行转换
     */
    public static <T> void unitAnnotationConvert(List<T> list) {
        for (T t : list) {
            // 获取属性字段
            Field[] declaredFields = t.getClass().getDeclaredFields();
            for (Field declaredField : declaredFields) {
                try {
                    if ("serialVersionUID".equals(declaredField.getName())) {
                        continue;
                    }
                    // 取出字段上的自定义注解
                    UnitConvert myFieldAnn = declaredField.getAnnotation(UnitConvert.class);
                    if (Objects.isNull(myFieldAnn)) {
                        continue;
                    }
                    // 取出注解里面的转换类型枚举
                    UnitEnum unitEnum = myFieldAnn.name();
                    // 赋予超级权限
                    declaredField.setAccessible(true);
                    Object object = declaredField.get(t);
                    if (Objects.nonNull(object)) {// 执行对应的转换操作(加减乘除)
                        // 元 → 千元
                        if (unitEnum.equals(UnitEnum.THOUSAND_YUAN)) {
                            BigDecimal bigDecimal = ((BigDecimal) object).divide(new BigDecimal("1000"), 2, RoundingMode.HALF_UP);
                            declaredField.set(t, bigDecimal);
                        }
                        // 元 → 万元
                        if (unitEnum.equals(UnitEnum.TEN_THOUSAND_YUAN)) {
                            BigDecimal bigDecimal = ((BigDecimal) object).divide(new BigDecimal("10000"), 2, RoundingMode.HALF_UP);
                            declaredField.set(t, bigDecimal);
                        }
                        // 百分比
                        if (unitEnum.equals(UnitEnum.PERCENTAGE)) {
                            BigDecimal bigDecimal = ((BigDecimal) object).multiply(new BigDecimal("100")).setScale(2, RoundingMode.HALF_UP);
                            declaredField.set(t, bigDecimal);
                        }
                        // 千分比
                        if (unitEnum.equals(UnitEnum.PER_MILLAGE)) {
                            BigDecimal bigDecimal = ((BigDecimal) object).multiply(new BigDecimal("1000")).setScale(2, RoundingMode.HALF_UP);
                            declaredField.set(t, bigDecimal);
                        }
                        // 千米 → 米
                        if (unitEnum.equals(UnitEnum.METER)) {
                            BigDecimal bigDecimal = ((BigDecimal) object).multiply(new BigDecimal("1000")).setScale(2, RoundingMode.HALF_UP);
                            declaredField.set(t, bigDecimal);
                        }
                        // 米 → 千米
                        if (unitEnum.equals(UnitEnum.KILOMETRE)) {
                            BigDecimal bigDecimal = ((BigDecimal) object).divide(new BigDecimal("1000"), 2, RoundingMode.HALF_UP);
                            declaredField.set(t, bigDecimal);
                        }
                        // 吨 → 千克
                        if (unitEnum.equals(UnitEnum.KILOGRAM)) {
                            BigDecimal bigDecimal = ((BigDecimal) object).multiply(new BigDecimal("1000")).setScale(2, RoundingMode.HALF_UP);
                            declaredField.set(t, bigDecimal);
                        }
                        // 千克 → 吨
                        if (unitEnum.equals(UnitEnum.TON)) {
                            BigDecimal bigDecimal = ((BigDecimal) object).divide(new BigDecimal("1000"), 2, RoundingMode.HALF_UP);
                            declaredField.set(t, bigDecimal);
                        }
                    }
                } catch (Exception e) {
                    log.error("单位转换失败,{}", e.getMessage());
                }
            }
        }
    }

    public static void main(String[] args) {

        // 创建测试数据
        UnitConvertVo vo = new UnitConvertVo();
        vo.setDailySales(new BigDecimal("23600.53"));
        vo.setAnnualSales(new BigDecimal("368624.24"));
        vo.setPercentage(new BigDecimal("0.2361"));
        vo.setPerMillage(new BigDecimal("0.536285"));
        vo.setDistance(new BigDecimal("8568.54"));// 米 → 千米
        vo.setWeight(new BigDecimal("35.62638"));// 吨 → 千克

        UnitConvertVo vo1 = new UnitConvertVo();
        vo1.setDailySales(new BigDecimal("23600.53"));
        vo1.setAnnualSales(new BigDecimal("368624.24"));
        vo1.setPercentage(new BigDecimal("0.2361"));
        vo1.setPerMillage(new BigDecimal("0.536285"));
        vo1.setDistance(new BigDecimal("8.56854"));// 千米 → 米
        vo1.setWeight(new BigDecimal("35626.38"));// 千克 → 吨

        List<UnitConvertVo> list1 = new ArrayList<>();
        List<UnitConvertVo> list2 = new ArrayList<>();
        list1.add(vo);
        list2.add(vo1);

        // 测试方法一:
        Map<String, UnitEnum> map = new HashMap<>();
        map.put("dailySales", UnitEnum.THOUSAND_YUAN);
        map.put("annualSales", UnitEnum.TEN_THOUSAND_YUAN);
        map.put("percentage", UnitEnum.PERCENTAGE);
        map.put("perMillage", UnitEnum.PER_MILLAGE);
        map.put("distance", UnitEnum.KILOMETRE);
        map.put("weight", UnitEnum.KILOGRAM);
        System.out.println("转换前:" + list1);
        unitMapConvert(list1, map);
        System.out.println("通过map标识转换:" + list1);

        // 测试方法二:
        System.out.println("转换前:" + list2);
        unitAnnotationConvert(list2);
        System.out.println("通过注解标识转换:" + list2);
    }

}

结果:

两种方法都正确的转换了单位,不过我个人推荐第二种方法,方便后期维护。

如果这篇文章对您有所帮助,或者有所启发的话,求一键三连:点赞、评论、收藏?关注,您的支持是我坚持写作最大的动力。??

文章来源:https://blog.csdn.net/weixin_42555014/article/details/135553264
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。