利用递归遍历获取Java复杂对象(对象的属性仍是对象//list/map)中指定属性的值(一)

冷不防 2022-04-17 03:16 1788阅读 0赞

本示例中又三个对象嵌套:

UserBO:复杂对象,其中一个属性是List或者Map

AddressBO:其中一个属性是SubAddressBO

SubAddressBO:包含目标属性addrId,且是string类型,查找addrId的值

任务:UserBO是一个复杂对象,该对象中肯定存在目标属性addrId(String类型,递归方法只能找string类型的属性,找其他类型自行修改代码),只是不知道addrId在哪个子属性中,如果UserBO存在多个addrId属性,那么只遍历出遇到的第一个addrId的值即可。

注意:(本例子在遍历复杂对象时,如果找到第一个目标属性,则退出,不在继续遍历,后面bolg有遍历复杂对象所有属性的文章)

1、本示例提供了两种方法来获取复杂对象中指定属性的值,一种是利用递归,另一种是直接把复杂对象转换成json串,再截取。

2、本示例对于复杂对象中不包含目标属性时,会返回空字符串。

3、目标属性可以存在于自定义类、list、map、数组中

4、**复杂对象可以是复杂嵌套的BO/List/Map,目标属性存在于BO中**

5、对于复杂对象是这种嵌套格式(**List>/List>/Map>)的没有做测试**

现在任务交代清楚了,开始贴代码

1、三个Bo类代码

  1. import java.io.Serializable;
  2. import java.util.List;
  3. import java.util.Map;
  4. public class UserBO implements Serializable {
  5. private static final long serialVersionUID = 1L;
  6. private String id;
  7. private String userName;
  8. private int age;
  9. private AddressBO address;
  10. private List<AddressBO> list;
  11. private Map<String,AddressBO> map;
  12. // private Date date;
  13. //
  14. // public Date getDate() {
  15. // return date;
  16. // }
  17. //
  18. // public void setDate(Date date) {
  19. // this.date = date;
  20. // }
  21. private byte b;
  22. private short s;
  23. private boolean bool;
  24. private double dble;
  25. private Byte bb;
  26. private Short ss;
  27. private Integer integer;
  28. private Long aLong;
  29. private Double dd;
  30. private Boolean aBoolean;
  31. private AddressBO[] addressArr;
  32. public UserBO() {
  33. }
  34. public UserBO(String id, String userName, int age, AddressBO address) {
  35. super();
  36. this.id = id;
  37. this.userName = userName;
  38. this.age = age;
  39. this.address = address;
  40. }
  41. public String getId() {
  42. return id;
  43. }
  44. public void setId(String id) {
  45. this.id = id;
  46. }
  47. public String getUserName() {
  48. return userName;
  49. }
  50. public void setUserName(String userName) {
  51. this.userName = userName;
  52. }
  53. public int getAge() {
  54. return age;
  55. }
  56. public void setAge(int age) {
  57. this.age = age;
  58. }
  59. public AddressBO getAddress() {
  60. return address;
  61. }
  62. public void setAddress(AddressBO address) {
  63. this.address = address;
  64. }
  65. public List<AddressBO> getList() {
  66. return list;
  67. }
  68. public void setList(List<AddressBO> list) {
  69. this.list = list;
  70. }
  71. public Map<String, AddressBO> getMap() {
  72. return map;
  73. }
  74. public void setMap(Map<String, AddressBO> map) {
  75. this.map = map;
  76. }
  77. public byte getB() {
  78. return b;
  79. }
  80. public void setB(byte b) {
  81. this.b = b;
  82. }
  83. public short getS() {
  84. return s;
  85. }
  86. public void setS(short s) {
  87. this.s = s;
  88. }
  89. public boolean isBool() {
  90. return bool;
  91. }
  92. public void setBool(boolean bool) {
  93. this.bool = bool;
  94. }
  95. public double getDble() {
  96. return dble;
  97. }
  98. public void setDble(double dble) {
  99. this.dble = dble;
  100. }
  101. public Byte getBb() {
  102. return bb;
  103. }
  104. public void setBb(Byte bb) {
  105. this.bb = bb;
  106. }
  107. public Short getSs() {
  108. return ss;
  109. }
  110. public void setSs(Short ss) {
  111. this.ss = ss;
  112. }
  113. public Integer getInteger() {
  114. return integer;
  115. }
  116. public void setInteger(Integer integer) {
  117. this.integer = integer;
  118. }
  119. public Long getaLong() {
  120. return aLong;
  121. }
  122. public void setaLong(Long aLong) {
  123. this.aLong = aLong;
  124. }
  125. public Double getDd() {
  126. return dd;
  127. }
  128. public void setDd(Double dd) {
  129. this.dd = dd;
  130. }
  131. public Boolean getaBoolean() {
  132. return aBoolean;
  133. }
  134. public void setaBoolean(Boolean aBoolean) {
  135. this.aBoolean = aBoolean;
  136. }
  137. // @Override
  138. // public String toString() {
  139. // return "UserVo [id=" + id + ", userName=" + userName + ", age=" + age + ", address=[addrId=" + address.getAddrId() + ",addrName=" + address.getAddrName() + "] ]";
  140. // }
  141. public AddressBO[] getAddressArr() {
  142. return addressArr;
  143. }
  144. public void setAddressArr(AddressBO[] addressArr) {
  145. this.addressArr = addressArr;
  146. }
  147. }
  148. import java.io.Serializable;
  149. public class AddressBO implements Serializable {
  150. private static final long serialVersionUID = 1L;
  151. // private String addrId;
  152. private String addrName;
  153. private SubAddressBO subAddressBO;
  154. public AddressBO() {
  155. }
  156. // public AddressBO(String addrId, String addrName) {
  157. // super();
  158. // this.addrId = addrId;
  159. // this.addrName = addrName;
  160. // }
  161. //
  162. // public String getAddrId() {
  163. // return addrId;
  164. // }
  165. //
  166. // public void setAddrId(String addrId) {
  167. // this.addrId = addrId;
  168. // }
  169. public String getAddrName() {
  170. return addrName;
  171. }
  172. public void setAddrName(String addrName) {
  173. this.addrName = addrName;
  174. }
  175. public SubAddressBO getSubAddressBO() {
  176. return subAddressBO;
  177. }
  178. public void setSubAddressBO(SubAddressBO subAddressBO) {
  179. this.subAddressBO = subAddressBO;
  180. }
  181. }
  182. import java.io.Serializable;
  183. /**
  184. * @author: lsl
  185. * @date: 2018/11/12
  186. */
  187. public class SubAddressBO implements Serializable {
  188. private String addrId;
  189. private int len;
  190. public SubAddressBO() {
  191. }
  192. public SubAddressBO(String addrId, int len) {
  193. this.addrId = addrId;
  194. this.len = len;
  195. }
  196. public String getAddrId() {
  197. return addrId;
  198. }
  199. public void setAddrId(String addrId) {
  200. this.addrId = addrId;
  201. }
  202. public int getLen() {
  203. return len;
  204. }
  205. public void setLen(int len) {
  206. this.len = len;
  207. }
  208. }

2、递归遍历获取复杂对象的指定属性的值

  1. import com.alibaba.fastjson.JSON;
  2. import org.apache.commons.lang3.StringUtils;
  3. import java.beans.PropertyDescriptor;
  4. import java.lang.reflect.Field;
  5. import java.lang.reflect.Method;
  6. import java.util.*;
  7. /**
  8. * @author: lsl
  9. * @date: 2018/11/9
  10. */
  11. public class RecursionObject {
  12. public static void main(String[] args){
  13. //制造数据
  14. SubAddressBO subAddressBO0 = new SubAddressBO("subaddress0",10);
  15. SubAddressBO subAddressBO1 = new SubAddressBO("subaddress1",20);
  16. SubAddressBO subAddressBO2 = new SubAddressBO("subaddress2",30);
  17. SubAddressBO subAddressBO3 = new SubAddressBO("subaddress3",40);
  18. SubAddressBO subAddressBO4 = new SubAddressBO("subaddress4",50);
  19. AddressBO address0 = new AddressBO();
  20. address0.setSubAddressBO(subAddressBO0);
  21. AddressBO address1 = new AddressBO();
  22. address1.setSubAddressBO(subAddressBO1);
  23. AddressBO address2 = new AddressBO();
  24. address2.setSubAddressBO(subAddressBO2);
  25. AddressBO address3 = new AddressBO();
  26. address3.setSubAddressBO(subAddressBO3);
  27. AddressBO address4 = new AddressBO();
  28. address4.setSubAddressBO(subAddressBO4);
  29. UserBO userBO = new UserBO();
  30. HashMap<String,AddressBO> map = new HashMap<>();
  31. map.put("addr1",address1);
  32. map.put("addr2",address2);
  33. ArrayList<AddressBO> list = new ArrayList<>();
  34. list.add(address3);
  35. list.add(address4);
  36. TestBO testBO = new TestBO();
  37. testBO.setAaa("123");
  38. testBO.setBbb("456");
  39. userBO.setTestBO(testBO);
  40. TestVO testVO = new TestVO();
  41. testVO.setCcc("ccc11");
  42. testVO.setDdd("ddd22");
  43. userBO.setTestVO(testVO);
  44. List<TestBO> listTestBo = new ArrayList<>();
  45. listTestBo.add(testBO);
  46. userBO.setListTestBo(listTestBo);
  47. userBO.setId("u123");
  48. userBO.setUserName("lsl");
  49. userBO.setAge(22);
  50. //测试目标属性存在于对象属性是自定义类中
  51. userBO.setAddress(address0);
  52. //测试目标属性存在于对象属性是list的元素中
  53. userBO.setList(list);
  54. //测试目标属性存在于对象属性是list的元素中
  55. // userBO.setMap(map);
  56. //测试目标属性存在于对象属性的数组中
  57. // AddressBO[] arr = new AddressBO[]{address0,address1};
  58. // userBO.setAddressArr(arr);
  59. List<UserBO> userBOList = new ArrayList<>();
  60. userBOList.add(userBO);
  61. //利用方法一
  62. Map<String,Object> resultMap = recursionLoopThroughObj(userBO,"addrId");
  63. System.err.println("result:" + resultMap.get("proValue"));
  64. //利用方法二
  65. // String businessNoFromArg = getBusinessNoFromArg(userBO, "addrId");
  66. // System.err.println("businessNoFromArg=" + businessNoFromArg);
  67. }
  68. /**
  69. * 方法一:利用递归遍历
  70. * 用途:从复杂对象中递归遍历,获取string类型的目标属性名的值
  71. * 适用条件:该复杂对象中如果存在多个目标属性targetProName,遍历到第一个atargetProName则退出遍历
  72. * targetProName属性必须是string
  73. * targetProName可以存在自定义对象中、list、map、数组中
  74. * 如果复杂对象不包含目标属性则返回空字符串
  75. * 复杂对象可以是复杂嵌套的BO/List<BO>/Map<Object,BO>,目标属性存在于BO中
  76. * 对于复杂对象是list或map嵌套的不做支持。比如List<List<BO></BO>> /List<Map<object,BO>> / Map<object,List<BO>>
  77. * @param object 复杂对象
  78. * @param targetProName 目标属性名
  79. * @return
  80. */
  81. public static Map<String,Object> recursionLoopThroughObj(Object object,String targetProName){
  82. Map<String,Object> resultMap = new HashMap<>();
  83. Class clazz = null;
  84. String proValue = "";
  85. boolean loopFlag = true;
  86. resultMap.put("loopFlag",loopFlag);
  87. resultMap.put("proValue",proValue);
  88. try {
  89. if (object==null || checkObjectIsSysType(object)){
  90. //如果object是null/基本数据类型/包装类/日期类型,则不需要在递归调用
  91. resultMap.put("loopFlag",false);
  92. resultMap.put("proValue","");
  93. return resultMap;
  94. }
  95. if (object instanceof Map){
  96. Map map = (Map)object;
  97. Map<String,Object> objMap = new HashMap<>();
  98. if (map!=null && map.size()>0){
  99. Iterator iterator = map.values().iterator();
  100. while (iterator.hasNext()){
  101. objMap = recursionLoopThroughObj(iterator.next(),targetProName);
  102. if (!(boolean)objMap.get("loopFlag")){
  103. return objMap;
  104. }
  105. }
  106. }
  107. }
  108. clazz = object.getClass();
  109. Field[] fields = clazz.getDeclaredFields();
  110. for (Field field : fields) {
  111. String proType = field.getGenericType().toString();
  112. String proName = field.getName();
  113. System.err.println("proName:" + proName + ",proType:" + proType );
  114. if ("class java.lang.String".equals(proType) && targetProName.equals(proName)){
  115. field.setAccessible(true);
  116. proValue = (String)field.get(object);
  117. resultMap.put("loopFlag",false);
  118. resultMap.put("proValue",proValue);
  119. return resultMap;
  120. }else if ("byte".equals(proType) || "short".equals(proType) || "int".equals(proType)|| "long".equals(proType)|| "double".equals(proType) || "float".equals(proType) || "boolean".equals(proType) ){
  121. //属性是基本类型跳过
  122. continue;
  123. }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))){
  124. //属性是包装类跳过
  125. continue;
  126. }else if (proType.startsWith("java.util")){
  127. //属性是集合类型则遍历
  128. if (proType.startsWith("java.util.List")){
  129. //对List类型的属性遍历
  130. PropertyDescriptor descriptor = new PropertyDescriptor(field.getName(), clazz);
  131. Method method = descriptor.getReadMethod();
  132. List list = (List)method.invoke(object);
  133. Map<String,Object> objMap = new HashMap<>();
  134. if (list!=null && list.size()>0){
  135. int len = list.size();
  136. for (int i= 0;i<len;i++){
  137. objMap = recursionLoopThroughObj(list.get(i),targetProName);
  138. if (!(boolean)objMap.get("loopFlag")){
  139. return objMap;
  140. }
  141. }
  142. }
  143. }else if (proType.startsWith("java.util.Map")){
  144. //对Map类型的属性遍历
  145. PropertyDescriptor descriptor = new PropertyDescriptor(field.getName(), clazz);
  146. Method method = descriptor.getReadMethod();
  147. Map map = (Map)method.invoke(object);
  148. Map<String,Object> objMap = new HashMap<>();
  149. if (map!=null && map.size()>0){
  150. for (Object obj : map.values()){
  151. objMap = recursionLoopThroughObj(obj,targetProName);
  152. if (!(boolean)objMap.get("loopFlag")){
  153. return objMap;
  154. }
  155. }
  156. }
  157. }
  158. }else if(field.getType().isArray()){
  159. //属性是数组类型则遍历
  160. field.setAccessible(true);
  161. Object[] objArr = (Object[]) field.get(object);
  162. Map<String,Object> objMap = new HashMap<>();
  163. if (objArr!=null && objArr.length>0){
  164. for (Object arr : objArr){
  165. objMap = recursionLoopThroughObj(arr,targetProName);
  166. if (!(boolean)objMap.get("loopFlag")){
  167. return objMap;
  168. }
  169. }
  170. }
  171. }else {
  172. //class类型的遍历
  173. PropertyDescriptor descriptor = new PropertyDescriptor(field.getName(), clazz);
  174. Method method = descriptor.getReadMethod();
  175. Object obj = method.invoke(object);
  176. Map<String,Object> objMap = new HashMap<>();
  177. if (obj!= null){
  178. objMap = recursionLoopThroughObj(obj,targetProName);
  179. if (!(boolean)objMap.get("loopFlag")){
  180. return objMap;
  181. }
  182. }else {
  183. continue;
  184. }
  185. }
  186. }
  187. } catch (Exception e) {
  188. System.err.println("err:" + e);
  189. }
  190. return resultMap;
  191. }
  192. /**
  193. * 检查object是否为java的基本数据类型/包装类/java.util.Date/java.sql.Date
  194. * @param object
  195. * @return
  196. */
  197. public static boolean checkObjectIsSysType(Object object){
  198. String objType = object.getClass().toString();
  199. if ("byte".equals(objType) || "short".equals(objType) || "int".equals(objType)|| "long".equals(objType)|| "double".equals(objType) || "float".equals(objType) || "boolean".equals(objType)){
  200. return true;
  201. }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)){
  202. return true;
  203. }else {
  204. return false;
  205. }
  206. }
  207. /**
  208. * 方法二:从复杂对象中获取string类型的目标属性targetProName的值
  209. * 把对象转换成json字符串,然后截取第一次出现的targetProName的值
  210. * 适用条件:同方法一
  211. * @param object 复杂对象
  212. * @param targetProName 目标属性
  213. * @return
  214. */
  215. public static String getBusinessNoFromArg(Object object,String targetProName){
  216. String jsonString = JSON.toJSONString(object);
  217. System.err.println("jsonString=" + jsonString);
  218. jsonString = StringUtils.substringAfter(jsonString,"\""+targetProName + "\":\"");
  219. jsonString = StringUtils.substringBefore(jsonString,"\"");
  220. return jsonString;
  221. }
  222. }

3、addrId存在于map中运行结果图:

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2Roa2xzbA_size_16_color_FFFFFF_t_70

发表评论

表情:
评论列表 (有 0 条评论,1788人围观)

还没有评论,来说两句吧...

相关阅读