Java封裝實現(xiàn)自適應(yīng)的單位轉(zhuǎn)換工具類
前言
平時在做項目中,經(jīng)常會做一些數(shù)據(jù)書籍,尤其像是數(shù)據(jù)看板之類,需要從數(shù)據(jù)庫中查詢想要的數(shù)據(jù),但這些數(shù)據(jù)的單位往往與需求是不匹配的。
比如,數(shù)據(jù)庫中查詢的金額是元,但頁面上需要展示萬元;
亦或是,數(shù)據(jù)庫中查出的距離是米,業(yè)務(wù)需要的是千米;
又比如,需要將查出的數(shù)據(jù)除以100,返回前端做百分比展示。等等。。。。。。
那像這種情況,我們是怎么處理的呢?
很多時候我們拿到的是一個數(shù)據(jù)集合list,然后去遍歷集合獲取每個參數(shù),再根據(jù)參數(shù)的屬性去做相關(guān)的單位轉(zhuǎn)換處理。然后一直重復(fù)做著get set,get set,get set。
像這樣:
雖然這種寫法不會報錯,但是看著重復(fù)的get set方法,著實是有點孬。所以就封裝了一個單位轉(zhuǎn)換的工具類,請看正文。
1、前期準(zhǔn)備
接收數(shù)據(jù)的實體類:
import lombok.Data; import java.io.Serializable; import java.math.BigDecimal; /** * 單位轉(zhuǎn)換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; }
定義單位類型枚舉類
/** * 單位轉(zhuǎn)換枚舉 */ 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、實現(xiàn)代碼
提供兩種方法實現(xiàn):
2.1 方法一:通過map去標(biāo)記需要轉(zhuǎn)換的 類屬性字段
思路:
1.通過反射取出字段
2.配合傳入的轉(zhuǎn)換標(biāo)記Map,匹配哪些字段需要轉(zhuǎn)換
3.然后從Map中取出相關(guān)字段的具體操作有哪些,然后執(zhí)行轉(zhuǎn)換
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; /** * 單位轉(zhuǎn)換工具類 */ @Slf4j public class UnitConvertUtil { /** * 方法一:通過反射,獲取標(biāo)識map進(jìn)行轉(zhuǎn)換 */ 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里的字段屬性和轉(zhuǎn)換操作 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) {// 若匹配上,則執(zhí)行對應(yīng)的轉(zhuǎn)換操作(加減乘除) // 元 → 千元 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("單位轉(zhuǎn)換失敗,{}", e.getMessage()); } } } } } }
寫個測試main方法:
public static void main(String[] args) { // 創(chuàng)建測試數(shù)據(jù) 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("轉(zhuǎn)換前:" + list1); unitMapConvert(list1, map); System.out.println("通過map標(biāo)識轉(zhuǎn)換:" + list1); }
轉(zhuǎn)換結(jié)果:
2.2 方法二:配合自定義注解
其實第一種方法已經(jīng)夠用了,但是為了調(diào)用更加的方便,后期能夠更好的拓展,所以配合著自定義注解,優(yōu)化了一下,直接上代碼:
定義自定義注解
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; /** * 單位轉(zhuǎn)換 自定義注解 */ @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; /** * 單位轉(zhuǎn)換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; }
配合自定義注解,在剛剛的工具類里又封裝了一個方法,反射獲取屬性字段,解析注解,做對應(yīng)轉(zhuǎn)換操作。
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.*; /** * 單位轉(zhuǎn)換工具類 */ @Slf4j public class UnitConvertUtil { /** * 方法一:通過反射,獲取標(biāo)識map進(jìn)行轉(zhuǎn)換 */ 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里的字段屬性和轉(zhuǎn)換操作 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) {// 若匹配上,則執(zhí)行對應(yīng)的轉(zhuǎn)換操作(加減乘除) // 元 → 千元 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("單位轉(zhuǎn)換失敗,{}", e.getMessage()); } } } } } /** * 方法二:通過自定義注解 進(jìn)行轉(zhuǎn)換 */ 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; } // 取出注解里面的轉(zhuǎn)換類型枚舉 UnitEnum unitEnum = myFieldAnn.name(); // 賦予超級權(quán)限 declaredField.setAccessible(true); Object object = declaredField.get(t); if (Objects.nonNull(object)) {// 執(zhí)行對應(yīng)的轉(zhuǎn)換操作(加減乘除) // 元 → 千元 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("單位轉(zhuǎn)換失敗,{}", e.getMessage()); } } } } public static void main(String[] args) { // 創(chuàng)建測試數(shù)據(jù) 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("轉(zhuǎn)換前:" + list1); unitMapConvert(list1, map); System.out.println("通過map標(biāo)識轉(zhuǎn)換:" + list1); // 測試方法二: System.out.println("轉(zhuǎn)換前:" + list2); unitAnnotationConvert(list2); System.out.println("通過注解標(biāo)識轉(zhuǎn)換:" + list2); } }
結(jié)果:
兩種方法都正確的轉(zhuǎn)換了單位,不過我個人推薦第二種方法,方便后期維護(hù)。
以上就是Java封裝實現(xiàn)自適應(yīng)的單位轉(zhuǎn)換工具類的詳細(xì)內(nèi)容,更多關(guān)于Java單位轉(zhuǎn)換的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
springBoot下實現(xiàn)java自動創(chuàng)建數(shù)據(jù)庫表
這篇文章主要介紹了springBoot下實現(xiàn)java自動創(chuàng)建數(shù)據(jù)庫表的操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-07-07IDEA使用Mybatis插件 MyBatisCodeHelper-Pro的圖文教程
這篇文章主要介紹了IDEA使用Mybatis插件 MyBatisCodeHelper-Pro的教程,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-09-09Java使用Sharding-JDBC分庫分表進(jìn)行操作
Sharding-JDBC 是無侵入式的 MySQL 分庫分表操作工具,本文主要介紹了Java使用Sharding-JDBC分庫分表進(jìn)行操作,感興趣的可以了解一下2021-08-08徹底理解Spring注解@Autowired實現(xiàn)原理
這篇文章主要為大家詳細(xì)的介紹了Spring注解@Autowired實現(xiàn)的原理,縝密的邏輯分析,實踐應(yīng)用示例操作說明,讓大家徹底的理解Spring注解@Autowired背后實現(xiàn)原理2022-03-03Spring整合Kaptcha谷歌驗證碼工具的開發(fā)步驟
這篇文章主要介紹了Spring整合Kaptcha谷歌驗證碼工具的開發(fā)步驟,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-01-01