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、前期準備
接收數(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去標記需要轉(zhuǎn)換的 類屬性字段
思路:
1.通過反射取出字段
2.配合傳入的轉(zhuǎn)換標記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 {
/**
* 方法一:通過反射,獲取標識map進行轉(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標識轉(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 {
/**
* 方法一:通過反射,獲取標識map進行轉(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());
}
}
}
}
}
/**
* 方法二:通過自定義注解 進行轉(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標識轉(zhuǎn)換:" + list1);
// 測試方法二:
System.out.println("轉(zhuǎn)換前:" + list2);
unitAnnotationConvert(list2);
System.out.println("通過注解標識轉(zhuǎn)換:" + list2);
}
}結(jié)果:

兩種方法都正確的轉(zhuǎn)換了單位,不過我個人推薦第二種方法,方便后期維護。
以上就是Java封裝實現(xiàn)自適應(yīng)的單位轉(zhuǎn)換工具類的詳細內(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-07
IDEA使用Mybatis插件 MyBatisCodeHelper-Pro的圖文教程
這篇文章主要介紹了IDEA使用Mybatis插件 MyBatisCodeHelper-Pro的教程,本文通過圖文并茂的形式給大家介紹的非常詳細,對大家的學(xué)習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-09-09
徹底理解Spring注解@Autowired實現(xiàn)原理
這篇文章主要為大家詳細的介紹了Spring注解@Autowired實現(xiàn)的原理,縝密的邏輯分析,實踐應(yīng)用示例操作說明,讓大家徹底的理解Spring注解@Autowired背后實現(xiàn)原理2022-03-03
Spring整合Kaptcha谷歌驗證碼工具的開發(fā)步驟
這篇文章主要介紹了Spring整合Kaptcha谷歌驗證碼工具的開發(fā)步驟,本文給大家介紹的非常詳細,對大家的學(xué)習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-01-01

