利用递归遍历获取Java复杂对象(对象的属性仍是对象//list/map)中指定属性的值(一)
本示例中又三个对象嵌套:
UserBO:复杂对象,其中一个属性是List
AddressBO:其中一个属性是SubAddressBO
SubAddressBO:包含目标属性addrId,且是string类型,查找addrId的值
任务:UserBO是一个复杂对象,该对象中肯定存在目标属性addrId(String类型,递归方法只能找string类型的属性,找其他类型自行修改代码),只是不知道addrId在哪个子属性中,如果UserBO存在多个addrId属性,那么只遍历出遇到的第一个addrId的值即可。
注意:(本例子在遍历复杂对象时,如果找到第一个目标属性,则退出,不在继续遍历,后面bolg有遍历复杂对象所有属性的文章)
1、本示例提供了两种方法来获取复杂对象中指定属性的值,一种是利用递归,另一种是直接把复杂对象转换成json串,再截取。
2、本示例对于复杂对象中不包含目标属性时,会返回空字符串。
3、目标属性可以存在于自定义类、list、map、数组中
4、**复杂对象可以是复杂嵌套的BO/List
5、对于复杂对象是这种嵌套格式(**List>/List
现在任务交代清楚了,开始贴代码
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;
}
}
还没有评论,来说两句吧...