在利用递归遍历获取Java复杂对象(对象的属性仍是对象//list/map)中指定属性的值(一)中我写了递归遍历复杂对象中目标属性,找到第一个目标属性则退出遍历。现在有遇到要遍历复杂对象中所有目标属性的值。且指定了属性所在类的类名、属性类型、属性名(当然也可以不指定这些,因为我是业务需要)。另外例子对属性为List或者Map的属性的遍历做了一定改动。
现在贴代码如下(如果各位同仁发现bug,望留言告知,多谢):
两个BO类:
public class PCodeTransDefPO implements Serializable { /** * */ private static final long serialVersionUID = -2806783975707171326L; private String seqNo; private String srcSysCode; private String destSysCode; private String transColumnName; private String srcCodeVal; private String destCodeVal; private Timestamp procTimestamp;
.........//省略了setter和getter方法
}
class TestClass{ private PCodeTransDefPO PCodeTransDefPO; private List<PCodeTransDefPO> arrayList = new ArrayList<>(); private Map<String,PCodeTransDefPO> hashMap = new HashMap<>(); public com.newcore.pcms.common.support.codetrans.models.po.pcms.PCodeTransDefPO getPCodeTransDefPO() { return PCodeTransDefPO; } public void setPCodeTransDefPO(com.newcore.pcms.common.support.codetrans.models.po.pcms.PCodeTransDefPO PCodeTransDefPO) { this.PCodeTransDefPO = PCodeTransDefPO; } public List<PCodeTransDefPO> getArrayList() { return arrayList; } public void setArrayList(List<PCodeTransDefPO> arrayList) { this.arrayList = arrayList; } public Map<String, PCodeTransDefPO> getHashMap() { return hashMap; } public void setHashMap(Map<String, PCodeTransDefPO> hashMap) { this.hashMap = hashMap; } }
递归类代码如下:
package com.newcore.pcms.common.support.codetrans.codetrans; import com.newcore.pcms.common.support.codetrans.codetrans.bo.ServiceAttrDictBO; import com.newcore.pcms.common.support.codetrans.models.po.pcms.PCodeTransDefPO; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.beans.IntrospectionException; import java.beans.PropertyDescriptor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; /** * @author: lsl * @date: 2018/11/29 */ public class CodeTransHolderUtils { private static Logger logger = LoggerFactory.getLogger(CodeTransHolderUtils.class); /** * 把t中指定attribute属性的值更改为dictCode,并把没有找到dictCode的attribute放到listNotIncludeAttr * 注意: * 1、t只能是javaBean,不能是list<BO>或者Map<K,BO> * 2、t中的属性类型不能是以下类型:Set、List<Map<K,V>、Map<K,List<BO>> * 3、t中的属性类型可以是BO、数组、List<BO>、Map<K,BO> * 4、属性名一定要规范,比如private PCodeTransDefPO pCodeTransDefPO(不规范),这样利用反射找不到getter方法,应该改成codeTransDefPO或者PCodeTransDefPO */ public static <T> void ergodicObject(String srcSysCode, String destSysCode, String forwardFlag, T t, String attrClass, String attrType, String attribute, List<String> listNotIncludeAttr, String dictCode) { String classType = t.getClass().getTypeName(); boolean sunFlag = classType.startsWith("java.") || classType.startsWith("javax.") || classType.startsWith("org."); if (t == null || checkObjectIsSysType(t) || sunFlag) { //如果object是null/基本数据类型,或者是sun公司提供的系统类,则不需要在递归调用 return; } Class clazz = t.getClass(); String className = t.getClass().getSimpleName(); String srcCodeVal = ""; Field[] fields = clazz.getDeclaredFields(); try { for (Field field : fields) { field.setAccessible(true); String proType = field.getGenericType().toString(); String attrShortName = field.getName(); if (attrClass.equals(className) && attrType.equals("String") && attribute.equals(attrShortName)) { // 获取object中是字典属性的值,并从数据库查询目标系统字典值, // 如果查询到目标系统字典值,把object中的字典属性值修改成目标系统的字典值, // 如果没有查询到目标系统的字典值,则把属性名添加到listNotIncludeAttr //TODO 目前暂只支持字典属性类型为String类型 srcCodeVal = (String) field.get(t); String destCodeVal = ""; if ("true".equals(forwardFlag)) {//调用正向码值转换方法 // destCodeVal = CodeTransDefTools.queryOneByCodeTypeAndDestSys(srcCodeVal, dictCode, srcSysCode, destSysCode); destCodeVal = "ccc333"; } else if ("false".equals(forwardFlag)) {//调用反向码值转换方法 //TODO } else { logger.info("数据库中存储该服务的forwardFlag不正确,正确应该是(true/false),实际是forwardFlag=" + forwardFlag); } if (destCodeVal != null && !"".equals(destCodeVal)) { field.set(t, destCodeVal); } else { listNotIncludeAttr.add(attribute); logger.info("在目标系统" + destSysCode + "中,没有找到源系统" + srcSysCode + "中属性是" + attribute + "对应的字典" + dictCode + ",找到的字典值是:" + destCodeVal); } } else if ("byte".equals(proType) || "short".equals(proType) || "int".equals(proType) || "long".equals(proType) || "double".equals(proType) || "float".equals(proType) || "boolean".equals(proType)) { //属性是基本类型跳过 continue; } else if ("class java.lang.Byte".equals(proType) || "class java.lang.Short".equals(proType) || "class java.lang.Integer".equals(proType) || "class java.lang.Long".equals(proType) || "class java.lang.Double".equals(proType) || "class java.lang.Float".equals(proType) || "class java.lang.Boolean".equals(proType) || ("class java.lang.String".equals(proType) && !attribute.equals(attrShortName))) { //属性是包装类跳过 continue; } else if (isList(field)) { //对List/ArrayList类型的属性遍历 try { PropertyDescriptor descriptor = new PropertyDescriptor(field.getName(), clazz); Method method = descriptor.getReadMethod(); List list = (List) method.invoke(t); if (list != null && list.size() > 0) { for (Object obj : list){ // 递归 ergodicObject(srcSysCode, destSysCode, forwardFlag, obj, attrClass, attrType, attribute, listNotIncludeAttr, dictCode); } } } catch (IntrospectionException e) { logger.info(e.getMessage()); } catch (InvocationTargetException e) { logger.info(e.getMessage()); } }else if(isMap(field)){ //对Map/HashMap类型的属性遍历 try { PropertyDescriptor descriptor = new PropertyDescriptor(field.getName(), clazz); Method method = descriptor.getReadMethod(); Map map = (Map) method.invoke(t); if (map != null && map.size() > 0) { for (Object obj : map.values()) { // 递归 ergodicObject(srcSysCode, destSysCode, forwardFlag, obj, attrClass, attrType, attribute, listNotIncludeAttr, dictCode); } } } catch (IntrospectionException e) { logger.info(e.getMessage()); } catch (InvocationTargetException e) { logger.info(e.getMessage()); } } else if (field.getType().isArray()) { //属性是数组类型则遍历 field.setAccessible(true); Object[] objArr = (Object[]) field.get(t); if (objArr != null && objArr.length > 0) { for (Object arr : objArr) { //递归 ergodicObject(srcSysCode, destSysCode, forwardFlag, arr, attrClass, attrType, attribute, listNotIncludeAttr, dictCode); } } } else { //class类型的遍历 try { PropertyDescriptor descriptor = new PropertyDescriptor(field.getName(), clazz); Method method = descriptor.getReadMethod(); Object obj = method.invoke(t); if (obj != null) { //递归 ergodicObject(srcSysCode, destSysCode, forwardFlag, obj, attrClass, attrType, attribute, listNotIncludeAttr, dictCode); } else { continue; } } catch (IntrospectionException e) { logger.info(e.getMessage()); } catch (InvocationTargetException e) { logger.info(e.getMessage()); } } } } catch (IllegalAccessException e) { logger.info(e.getMessage()); } } /** * 判断是否是List或者ArrayList * @param field * @return */ public static boolean isList(Field field){ boolean flag = false; String simpleName = field.getType().getSimpleName(); if ("List".equals(simpleName) || "ArrayList".equals(simpleName)){ flag = true; } return flag; } /** * 判断是否是Map或者HashMap * @param field * @return */ public static boolean isMap(Field field){ boolean flag = false; String simpleName = field.getType().getSimpleName(); if ("Map".equals(simpleName) || "HashMap".equals(simpleName)){ flag = true; } return flag; } /** * 检查object是否为java的基本数据类型 * * @param object * @return */ public static boolean checkObjectIsSysType(Object object) { String objType = object.getClass().toString(); if ("byte".equals(objType) || "short".equals(objType) || "int".equals(objType) || "long".equals(objType) || "double".equals(objType) || "float".equals(objType) || "boolean".equals(objType)) { return true; } else { return false; } } //============================================================================================== public static void main(String[] args) { PCodeTransDefPO bo = new PCodeTransDefPO(); bo.setSrcSysCode("BO000"); PCodeTransDefPO boList = new PCodeTransDefPO(); boList.setSrcSysCode("BOList"); PCodeTransDefPO boMap = new PCodeTransDefPO(); boMap.setSrcSysCode("BOMap"); TestClass testClass = new TestClass(); List<PCodeTransDefPO> list = new ArrayList<>(); list.add(boList); Map<String,PCodeTransDefPO> map = new HashMap<>(); map.put("11",boMap); testClass.setPCodeTransDefPO(bo); testClass.setArrayList(list); testClass.setHashMap(map); List<String> notAttrList = new ArrayList<>(); // loopObject(testClass); System.out.println("修改前,BO中的目标属性:"+ testClass.getPCodeTransDefPO().getSrcSysCode()); System.out.println("修改前,List中的目标属性:"+ testClass.getArrayList().get(0).getSrcSysCode()); System.out.println("修改前,Map中的目标属性:"+ testClass.getHashMap().get("11").getSrcSysCode()); ergodicObject("srcsys","destsys","true",testClass,"PCodeTransDefPO","String","srcSysCode",notAttrList,"sysDictCode"); System.out.println("修改后,BO中的目标属性:"+ testClass.getPCodeTransDefPO().getSrcSysCode()); System.out.println("修改后,List中的目标属性:"+ testClass.getArrayList().get(0).getSrcSysCode()); System.out.println("修改后,Map中的目标属性:"+ testClass.getHashMap().get("11").getSrcSysCode()); } } class TestClass{ private PCodeTransDefPO PCodeTransDefPO; private List<PCodeTransDefPO> arrayList = new ArrayList<>(); private Map<String,PCodeTransDefPO> hashMap = new HashMap<>(); public com.newcore.pcms.common.support.codetrans.models.po.pcms.PCodeTransDefPO getPCodeTransDefPO() { return PCodeTransDefPO; } public void setPCodeTransDefPO(com.newcore.pcms.common.support.codetrans.models.po.pcms.PCodeTransDefPO PCodeTransDefPO) { this.PCodeTransDefPO = PCodeTransDefPO; } public List<PCodeTransDefPO> getArrayList() { return arrayList; } public void setArrayList(List<PCodeTransDefPO> arrayList) { this.arrayList = arrayList; } public Map<String, PCodeTransDefPO> getHashMap() { return hashMap; } public void setHashMap(Map<String, PCodeTransDefPO> hashMap) { this.hashMap = hashMap; } }