通过反射+注解,计算集合中的数据,并生成汇总结果
实体类
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.math.BigDecimal;
/**
* TODO 类注释
*
* @author shuai
* @since 2023-03-04
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class TestVo {
@SummaryDesc
private String desc;
private int intField1;
private Integer intField2;
private BigDecimal bmField1;
private BigDecimal bmField2;
}
注解
import java.lang.annotation.*;
/**
* 定义数据汇总的描述字段
*
* @author shuai
* @since 2023-03-04
*/
@Documented
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface SummaryDesc {
}
工具类
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;
/**
* 数据汇总工具类
*
* @author shuai
* @since 2023-03-04
*/
@Slf4j
public class Utils {
/**
* 数据汇总(汇总int、Integer、BigDecimal类型)
* @param clazz class
* @param list 数据集合
* @param <T> T
* @return 汇总T
*/
public static <T> T getSum(Class<T> clazz, List<T> list){
return getSum(clazz,list,null,"合计");
}
/**
* 数据汇总(单一类型)
* @param clazz class
* @param list 数据集合
* @param type 汇总的字段类型 例:BigDecimal.class
* @param <T> T
* @return 汇总T
*/
public static <T> T getSum(Class<T> clazz, List<T> list ,Object type){
return getSum(clazz, list, type, "合计");
}
/**
* 数据汇总(汇总int、Integer、BigDecimal类型)
* @param clazz class
* @param list 数据集合
* @param <T> T
* @return 汇总T
*/
public static <T> T getSum(Class<T> clazz, List<T> list, String var){
return getSum(clazz, list, null, var);
}
/**
* 数据汇总
* @param clazz class
* @param list 数据集合
* @param type 汇总的字段类型
* @param var 汇总字段描述
* @param <T> T
* @return 汇总T
*/
public static <T> T getSum(Class<T> clazz, List<T> list,Object type, String var){
return getSumData(clazz, list, type, var);
}
/**
* 汇总的字段类型
* @param obj 字段类型
* @return 类型集合
*/
private static List<Object> getFieldTypes(Object obj){
if(null == obj){
return Arrays.asList(int.class, Integer.class, BigDecimal.class);
}
return Collections.singletonList(obj);
}
/**
* 数据汇总
* @param clazz class
* @param list 数据集合
* @param type 汇总的字段类型
* @param var 汇总字段描述
* @param <T> T
* @return 汇总T
*/
private static <T> T getSumData(Class<T> clazz, List<T> list, Object type, String var){
//汇总的字段类型
List<Object> types = getFieldTypes(type);
//获取class所有属性字段
Field[] fields = ReflectUtil.getFields(clazz);
//过滤出需要计算合计的字段
List<Field> fieldList = Arrays.stream(fields).filter(field -> types.contains(field.getType())).collect(Collectors.toList());
//汇总数据map
Map<String,Object> map = Maps.newHashMapWithExpectedSize(fieldList.size());
fieldList.forEach(field -> {
//开启访问权限
field.setAccessible(true);
list.stream().forEach(item->{
try {
if(field.getType() == int.class || field.getType() == Integer.class){
Integer now = ObjectUtil.isNull(field.get(item)) ? 0 : (Integer) field.get(item);
Integer oldSum = ObjectUtil.isNull(map.get(field.getName())) ? 0 : (Integer) map.get(field.getName());
map.put(field.getName(), now + oldSum);
}
if(field.getType() == BigDecimal.class){
BigDecimal now = ObjectUtil.isNull(field.get(item)) ? BigDecimal.ZERO : (BigDecimal) field.get(item);
BigDecimal oldSum = ObjectUtil.isNull(map.get(field.getName())) ? BigDecimal.ZERO : (BigDecimal) map.get(field.getName());
map.put(field.getName(), now.add(oldSum));
}
} catch (IllegalAccessException e) {
log.error(e.getMessage());
}
});
});
//实例化对象
T t = ReflectUtil.newInstance(clazz);
Arrays.stream(fields).forEach(field->{
//添加描述
SummaryDesc summaryDesc = field.getAnnotation(SummaryDesc.class);
if(ObjectUtil.isNotEmpty(summaryDesc)){
ReflectUtil.invoke(t,StrUtil.addPrefixIfNot(StrUtil.upperFirst(field.getName()),"set"),var);
return;
}
if(ObjectUtil.isNotEmpty(map.get(field.getName()))){
ReflectUtil.invoke(t,StrUtil.addPrefixIfNot(StrUtil.upperFirst(field.getName()),"set"),map.get(field.getName()));
}
});
return t;
}
}
测试类
import cn.hutool.core.collection.CollUtil;
import java.math.BigDecimal;
import java.util.List;
/**
* TODO 类注释
*
* @author shuai
* @since 2023-03-04
*/
public class Test {
private static List<TestVo> setTestVo(){
List<TestVo> vos = CollUtil.newArrayList();
for (int i = 1; i < 3; i++) {
TestVo vo = TestVo.builder().desc("test"+i).intField1(i).intField2(i*2)
.bmField1(BigDecimal.ONE.multiply(new BigDecimal(i)))
.bmField2(BigDecimal.ONE.multiply(new BigDecimal(i*2))).build();
vos.add(vo);
}
return vos;
}
public static void main(String[] args) {
List<TestVo> testVos = setTestVo();
testVos.add(Utils.getSum(TestVo.class,testVos));
testVos.forEach(System.out::println);
}
}
运行结果
1.汇总数据
Utils.getSum(TestVo.class,testVos)
2.汇总某种字段类型的数据
Utils.getSum(TestVo.class,testVos,Integer.class)
3.汇总某种字段类型数据,自定义字段描述
Utils.getSum(TestVo.class,testVos,Integer.class,“测试汇总数据”)
4.汇总所有类型数据,自定义字段描述
Utils.getSum(TestVo.class,testVos,“测试汇总数据”)