背景
当需要将两个对象中多个同名的属性进行相加时,往往会出现如下代码段
User target = new User();
User u1 = new User();
u1.setJanuaryAmount(BigDecimal.valueOf(3.5));
u1.setFebruaryAmount(BigDecimal.valueOf(1.5));
User u2 = new User();
u2.setJanuaryAmount(BigDecimal.valueOf(5.2));
u2.setFebruaryAmount(BigDecimal.valueOf(22.5));
// 将u1和u2两对象同名的属性进行相加
target.setJanuaryAmount(u1.getJanuaryAmount().add(u2.getJanuaryAmount()));
target.setFebruaryAmount(u1.getFebruaryAmount().add(u2.getFebruaryAmount()));
当需要相加的属性过多时,将会出现一个属性相加则多一行target.setXXX()代码。
此时手写set方法将变得不再优雅。
创建一个简易实体User,包含Bigdecimal类型用于运算
public class User {
private String username;
private String ggg;
private BigDecimal januaryAmount;
private BigDecimal augustAmount;
private BigDecimal februaryAmount;
...
getter() && setter()
}
创建反射处理工具类reflexToAddFieldValue
private static void reflexToAddFieldValue(User source, User target){
try {
// 分别获取两对象的字段列表
Field[] sFields = source.getClass().getDeclaredFields();
Field[] tFields = target.getClass().getDeclaredFields();
for(Field sField:sFields){
// 若字段不为BigDecimal类型,则直接过滤
if(!sField.getType().getName().contains("BigDecimal")){
continue;
}
String sName = sField.getName();
for(Field tField:tFields){
// 若字段不为BigDecimal类型,则直接过滤
if(!tField.getType().getName().contains("BigDecimal")){
continue;
}
String tName = tField.getName();
// 两不同对象的字段类型相同时,则对数据进行相加操作
if(sName.equals(tName)){
// 关闭两字段的安全检查
sField.setAccessible(true);
tField.setAccessible(true);
BigDecimal sDecimal = (BigDecimal)sField.get(source);
BigDecimal tDecimal = (BigDecimal)tField.get(target);
BigDecimal finalDecimal = null;
// 若均存在,则两者值相加;仅一方存在则直接赋予
if(sDecimal!=null && tDecimal!=null){
finalDecimal = sDecimal.add(tDecimal);
} else if(sDecimal!=null && tDecimal==null){
finalDecimal = sDecimal;
} else if (sDecimal==null && tDecimal!=null){
finalDecimal = tDecimal;
} else {
sField.setAccessible(false);
tField.setAccessible(false);
continue;
}
// 将计算出的值重新赋予目标对象进行返回
tField.set(target, finalDecimal);
sField.setAccessible(false);
tField.setAccessible(false);
}
}
}
} catch (Exception e){
LOGGER.error("程序处理异常", e);
}
}
使用main方法测试
public static void main(String[] args) {
try{
List list = new ArrayList<>();
User u1 = new User();
u1.setUsername("shanghai");
u1.setGgg("阳光");
u1.setJanuaryAmount(BigDecimal.valueOf(3.5));
User u2 = new User();
u2.setUsername("shanghai");
u2.setGgg("沙滩");
u2.setAugustAmount(BigDecimal.valueOf(3.5));
User u3 = new User();
u3.setUsername("shumin");
u3.setGgg("海浪");
u3.setJanuaryAmount(BigDecimal.valueOf(4));
User u4 = new User();
u4.setUsername("shumin");
u4.setGgg("仙人掌");
u4.setJanuaryAmount(BigDecimal.valueOf(3.5));
User u5 = new User();
u5.setUsername("aaa");
u5.setGgg("老船长");
u5.setJanuaryAmount(BigDecimal.valueOf(3.5));
u5.setFebruaryAmount(BigDecimal.valueOf(2));
User u6 = new User();
u6.setUsername("aaa");
u6.setGgg("小孩");
u6.setJanuaryAmount(BigDecimal.valueOf(3.5));
u6.setFebruaryAmount(BigDecimal.valueOf(888));
list.add(u1);
list.add(u2);
list.add(u3);
list.add(u4);
list.add(u5);
list.add(u6);
List targetVOList = new ArrayList<>();
// 按属性username分组
Map> map = list.stream().collect(Collectors.groupingBy(User::getUsername));
for(String username:map.keySet()){
List mapByUsernameList = map.get(username);
// 设置目标对象
User targetVO = new User();
StringBuilder nameBuilder = new StringBuilder();
for(int i=0;i
控制台输出
10:25:08.261 [main] INFO cn.gdxiash.consumer.test.Test01 - User{username='aaa', ggg='老船长,小孩', januaryAmount=7.0, februaryAmount=890, augustAmount=null}
10:25:08.267 [main] INFO cn.gdxiash.consumer.test.Test01 - User{username='shanghai', ggg='阳光,沙滩', januaryAmount=3.5, februaryAmount=null,augustAmount=3.5}
10:25:08.267 [main] INFO cn.gdxiash.consumer.test.Test01 - User{username='shumin', ggg='海浪,仙人掌', januaryAmount=7.5, februaryAmount=null, augustAmount=null}