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