Java封装实现自适应的单位转换工具类
目录
- 前言
- 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; /*** 营收占比(百分比)*www.devze.com/ @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); } php // 元 → 万元 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", UnitandroidEnum.KILOGRAM); System.out.println("转换前:" + list1); unitMapConvert(list1, map); System.out.println("通过map标识转换:" + list1); // 测试方法二: System.out.println("转换前:" + list2); unitAnnotationConvert(list2); System.out.println("通过注解标识转换:" + list2); } }
结果:
两种方法都正确的转换了单位,不过我个人推荐第二种方法,方便后期维护。
以上就是Java封装实现自适应的单位转换工具类的详细内容,更多关于Java单位转换的资料请关注编程客栈(www.devze.com)其它相关文章!
精彩评论