1. 程式人生 > >利用遞迴遍歷獲取Java複雜物件(物件的屬性仍是物件//list/map)中指定屬性的值

利用遞迴遍歷獲取Java複雜物件(物件的屬性仍是物件//list/map)中指定屬性的值

本示例中又三個物件巢狀:

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;
    }
}

3、addrId存在於map中執行結果圖: