利用遞迴遍歷獲取Java複雜物件(物件的屬性仍是物件//list/map)中指定屬性的值
阿新 • • 發佈:2018-11-26
本示例中又三個物件巢狀:
UserBO:複雜物件,其中一個屬性是List<AddressBO>或者Map<AddressBO>
AddressBO:其中一個屬性是SubAddressBO
SubAddressBO:包含目標屬性addrId,且是string型別,查詢addrId的值
任務:UserBO是一個複雜物件,該物件中肯定存在目標屬性addrId(String型別,遞迴方法只能找string型別的屬性,找其他型別自行修改程式碼),只是不知道addrId在哪個子屬性中,如果UserBO存在多個addrId屬性,那麼只遍歷出遇到的第一個addrId的值即可。
注意:
1、本示例提供了兩種方法來獲取複雜物件中指定屬性的值,一種是利用遞迴,另一種是直接把複雜物件轉換成json串,再擷取。
2、本示例對於複雜物件中不包含目標屬性時,會返回空字串。
3、目標屬性可以存在於自定義類、list、map、陣列中
4、複雜物件可以是複雜巢狀的BO/List<BO>/Map<Object,BO>,目標屬性存在於BO中
5、對於複雜物件是這種巢狀格式(List<List<BO>> /List<Map<Object,BO>>/Map<Object,List<BO>>)的沒有做測試
現在任務交代清楚了,開始貼程式碼
1、三個Bo類程式碼
import java.io.Serializable; import java.util.List; import java.util.Map; public class UserBO implements Serializable { private static final long serialVersionUID = 1L; private String id; private String userName; private int age; private AddressBO address; private List<AddressBO> list; private Map<String,AddressBO> map; // private Date date; // // public Date getDate() { // return date; // } // // public void setDate(Date date) { // this.date = date; // } private byte b; private short s; private boolean bool; private double dble; private Byte bb; private Short ss; private Integer integer; private Long aLong; private Double dd; private Boolean aBoolean; private AddressBO[] addressArr; public UserBO() { } public UserBO(String id, String userName, int age, AddressBO address) { super(); this.id = id; this.userName = userName; this.age = age; this.address = address; } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public AddressBO getAddress() { return address; } public void setAddress(AddressBO address) { this.address = address; } public List<AddressBO> getList() { return list; } public void setList(List<AddressBO> list) { this.list = list; } public Map<String, AddressBO> getMap() { return map; } public void setMap(Map<String, AddressBO> map) { this.map = map; } public byte getB() { return b; } public void setB(byte b) { this.b = b; } public short getS() { return s; } public void setS(short s) { this.s = s; } public boolean isBool() { return bool; } public void setBool(boolean bool) { this.bool = bool; } public double getDble() { return dble; } public void setDble(double dble) { this.dble = dble; } public Byte getBb() { return bb; } public void setBb(Byte bb) { this.bb = bb; } public Short getSs() { return ss; } public void setSs(Short ss) { this.ss = ss; } public Integer getInteger() { return integer; } public void setInteger(Integer integer) { this.integer = integer; } public Long getaLong() { return aLong; } public void setaLong(Long aLong) { this.aLong = aLong; } public Double getDd() { return dd; } public void setDd(Double dd) { this.dd = dd; } public Boolean getaBoolean() { return aBoolean; } public void setaBoolean(Boolean aBoolean) { this.aBoolean = aBoolean; } // @Override // public String toString() { // return "UserVo [id=" + id + ", userName=" + userName + ", age=" + age + ", address=[addrId=" + address.getAddrId() + ",addrName=" + address.getAddrName() + "] ]"; // } public AddressBO[] getAddressArr() { return addressArr; } public void setAddressArr(AddressBO[] addressArr) { this.addressArr = addressArr; } }
import java.io.Serializable; public class AddressBO implements Serializable { private static final long serialVersionUID = 1L; // private String addrId; private String addrName; private SubAddressBO subAddressBO; public AddressBO() { } // public AddressBO(String addrId, String addrName) { // super(); // this.addrId = addrId; // this.addrName = addrName; // } // // public String getAddrId() { // return addrId; // } // // public void setAddrId(String addrId) { // this.addrId = addrId; // } public String getAddrName() { return addrName; } public void setAddrName(String addrName) { this.addrName = addrName; } public SubAddressBO getSubAddressBO() { return subAddressBO; } public void setSubAddressBO(SubAddressBO subAddressBO) { this.subAddressBO = subAddressBO; } }
import java.io.Serializable; /** * @author: lsl * @date: 2018/11/12 */ public class SubAddressBO implements Serializable { private String addrId; private int len; public SubAddressBO() { } public SubAddressBO(String addrId, int len) { this.addrId = addrId; this.len = len; } public String getAddrId() { return addrId; } public void setAddrId(String addrId) { this.addrId = addrId; } public int getLen() { return len; } public void setLen(int len) { this.len = len; } }
2、遞迴遍歷獲取複雜物件的指定屬性的值
import com.alibaba.fastjson.JSON; import org.apache.commons.lang3.StringUtils; import java.beans.PropertyDescriptor; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.*; /** * @author: lsl * @date: 2018/11/9 */ public class RecursionObject { public static void main(String[] args){ //製造資料 SubAddressBO subAddressBO0 = new SubAddressBO("subaddress0",10); SubAddressBO subAddressBO1 = new SubAddressBO("subaddress1",20); SubAddressBO subAddressBO2 = new SubAddressBO("subaddress2",30); SubAddressBO subAddressBO3 = new SubAddressBO("subaddress3",40); SubAddressBO subAddressBO4 = new SubAddressBO("subaddress4",50); AddressBO address0 = new AddressBO(); address0.setSubAddressBO(subAddressBO0); AddressBO address1 = new AddressBO(); address1.setSubAddressBO(subAddressBO1); AddressBO address2 = new AddressBO(); address2.setSubAddressBO(subAddressBO2); AddressBO address3 = new AddressBO(); address3.setSubAddressBO(subAddressBO3); AddressBO address4 = new AddressBO(); address4.setSubAddressBO(subAddressBO4); UserBO userBO = new UserBO(); HashMap<String,AddressBO> map = new HashMap<>(); map.put("addr1",address1); map.put("addr2",address2); ArrayList<AddressBO> list = new ArrayList<>(); list.add(address3); list.add(address4); TestBO testBO = new TestBO(); testBO.setAaa("123"); testBO.setBbb("456"); userBO.setTestBO(testBO); TestVO testVO = new TestVO(); testVO.setCcc("ccc11"); testVO.setDdd("ddd22"); userBO.setTestVO(testVO); List<TestBO> listTestBo = new ArrayList<>(); listTestBo.add(testBO); userBO.setListTestBo(listTestBo); userBO.setId("u123"); userBO.setUserName("lsl"); userBO.setAge(22); //測試目標屬性存在於物件屬性是自定義類中 userBO.setAddress(address0); //測試目標屬性存在於物件屬性是list的元素中 userBO.setList(list); //測試目標屬性存在於物件屬性是list的元素中 // userBO.setMap(map); //測試目標屬性存在於物件屬性的陣列中 // AddressBO[] arr = new AddressBO[]{address0,address1}; // userBO.setAddressArr(arr); List<UserBO> userBOList = new ArrayList<>(); userBOList.add(userBO); //利用方法一 Map<String,Object> resultMap = recursionLoopThroughObj(userBO,"addrId"); System.err.println("result:" + resultMap.get("proValue")); //利用方法二 // String businessNoFromArg = getBusinessNoFromArg(userBO, "addrId"); // System.err.println("businessNoFromArg=" + businessNoFromArg); } /** * 方法一:利用遞迴遍歷 * 用途:從複雜物件中遞迴遍歷,獲取string型別的目標屬性名的值 * 適用條件:該複雜物件中如果存在多個目標屬性targetProName,遍歷到第一個atargetProName則退出遍歷 * targetProName屬性必須是string * targetProName可以存在自定義物件中、list、map、陣列中 * 如果複雜物件不包含目標屬性則返回空字串 * 複雜物件可以是複雜巢狀的BO/List<BO>/Map<Object,BO>,目標屬性存在於BO中 * 對於複雜物件是list或map巢狀的不做支援。比如List<List<BO></BO>> /List<Map<object,BO>> / Map<object,List<BO>> * @param object 複雜物件 * @param targetProName 目標屬性名 * @return */ public static Map<String,Object> recursionLoopThroughObj(Object object,String targetProName){ Map<String,Object> resultMap = new HashMap<>(); Class clazz = null; String proValue = ""; boolean loopFlag = true; resultMap.put("loopFlag",loopFlag); resultMap.put("proValue",proValue); try { if (object==null || checkObjectIsSysType(object)){ //如果object是null/基本資料型別/包裝類/日期型別,則不需要在遞迴呼叫 resultMap.put("loopFlag",false); resultMap.put("proValue",""); return resultMap; } if (object instanceof Map){ Map map = (Map)object; Map<String,Object> objMap = new HashMap<>(); if (map!=null && map.size()>0){ Iterator iterator = map.values().iterator(); while (iterator.hasNext()){ objMap = recursionLoopThroughObj(iterator.next(),targetProName); if (!(boolean)objMap.get("loopFlag")){ return objMap; } } } } clazz = object.getClass(); Field[] fields = clazz.getDeclaredFields(); for (Field field : fields) { String proType = field.getGenericType().toString(); String proName = field.getName(); System.err.println("proName:" + proName + ",proType:" + proType ); if ("class java.lang.String".equals(proType) && targetProName.equals(proName)){ field.setAccessible(true); proValue = (String)field.get(object); resultMap.put("loopFlag",false); resultMap.put("proValue",proValue); return resultMap; }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) && !targetProName.equals(proName))){ //屬性是包裝類跳過 continue; }else if (proType.startsWith("java.util")){ //屬性是集合型別則遍歷 if (proType.startsWith("java.util.List")){ //對List型別的屬性遍歷 PropertyDescriptor descriptor = new PropertyDescriptor(field.getName(), clazz); Method method = descriptor.getReadMethod(); List list = (List)method.invoke(object); Map<String,Object> objMap = new HashMap<>(); if (list!=null && list.size()>0){ int len = list.size(); for (int i= 0;i<len;i++){ objMap = recursionLoopThroughObj(list.get(i),targetProName); if (!(boolean)objMap.get("loopFlag")){ return objMap; } } } }else if (proType.startsWith("java.util.Map")){ //對Map型別的屬性遍歷 PropertyDescriptor descriptor = new PropertyDescriptor(field.getName(), clazz); Method method = descriptor.getReadMethod(); Map map = (Map)method.invoke(object); Map<String,Object> objMap = new HashMap<>(); if (map!=null && map.size()>0){ for (Object obj : map.values()){ objMap = recursionLoopThroughObj(obj,targetProName); if (!(boolean)objMap.get("loopFlag")){ return objMap; } } } } }else if(field.getType().isArray()){ //屬性是陣列型別則遍歷 field.setAccessible(true); Object[] objArr = (Object[]) field.get(object); Map<String,Object> objMap = new HashMap<>(); if (objArr!=null && objArr.length>0){ for (Object arr : objArr){ objMap = recursionLoopThroughObj(arr,targetProName); if (!(boolean)objMap.get("loopFlag")){ return objMap; } } } }else { //class型別的遍歷 PropertyDescriptor descriptor = new PropertyDescriptor(field.getName(), clazz); Method method = descriptor.getReadMethod(); Object obj = method.invoke(object); Map<String,Object> objMap = new HashMap<>(); if (obj!= null){ objMap = recursionLoopThroughObj(obj,targetProName); if (!(boolean)objMap.get("loopFlag")){ return objMap; } }else { continue; } } } } catch (Exception e) { System.err.println("err:" + e); } return resultMap; } /** * 檢查object是否為java的基本資料型別/包裝類/java.util.Date/java.sql.Date * @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 if ("class java.lang.Byte".equals(objType) || "class java.lang.Short".equals(objType) || "class java.lang.Integer".equals(objType) || "class java.lang.Long".equals(objType) || "class java.lang.Double".equals(objType) || "class java.lang.Float".equals(objType) || "class java.lang.Boolean".equals(objType) || "class java.lang.String".equals(objType)){ return true; }else { return false; } } /** * 方法二:從複雜物件中獲取string型別的目標屬性targetProName的值 * 把物件轉換成json字串,然後擷取第一次出現的targetProName的值 * 適用條件:同方法一 * @param object 複雜物件 * @param targetProName 目標屬性 * @return */ public static String getBusinessNoFromArg(Object object,String targetProName){ String jsonString = JSON.toJSONString(object); System.err.println("jsonString=" + jsonString); jsonString = StringUtils.substringAfter(jsonString,"\""+targetProName + "\":\""); jsonString = StringUtils.substringBefore(jsonString,"\""); return jsonString; } }