如何在java中递归地找到不同级别的属性值

  • 本文关键字:属性 java 递归 java java-8
  • 更新时间 :
  • 英文 :


寻找查找不同层次结构上的类的属性值的通用解决方案。该方法的输入将仅为属性名称(如"name"),然后我应该能够找到该属性的值。

我的类的结构如下所示:

class Student {
private String id;
private String name;
private List<Address> addresses;
private Map<String, String> customAttributes;
}
class Address {
private String city;
private String state;
private PhoneNumbers phoneNumbers;
...
getter setter
}
class PhoneNumbers {
private PhoneNumber phoneNumber1;
private PhoneNumber phoneNumber2;
..
getter setter
}
class PhoneNumber {
private String code;
private String number;
...
getter setter
}

很容易找到学生级别的值,在这种情况下,我可以创建<属性映射,getter>然后我就能找到值了

但是在当前的场景中,有不同的级别,自定义属性映射和记录的数量很高(如10,000或更多)。

所以方法的输入可以是任何东西,比如:

private String getAttributeValue(String attributeName) {

}
var phoneNumber1 = new PhoneNumber("012", "233223");
var phoneNumber2 = new PhoneNumber("91", "23323223");
var phoneNumbers = new PhoneNumbers(phoneNumber1, phoneNumber2);
var address1 = new Address("city1", "state1", phoneNumbers);
var address2 = new Address("city123", "state1", phoneNumbers);
var customAttributes = Map.of(
"attr1", "value1",
"attr2", "value2"
);
var student = new Student(1, "xyz", List.of(address1, address2), customAttributes);
city -> city123
attr2 -> value2
code -> 012
number -> 23323223

请在这里帮助我,如果有人实现了类似的解决方案。

对于通用方式,请查看Java的ReflectionAPI,例如:

final Field[] declaredFields = source.getClass().getDeclaredFields();

您可以获得所有声明的字段,并使用它们来获取特定字段的值,通过名称或类型等过滤它们。使用它,您将能够很容易地构建像getValueByName(object,"fieldName")这样的api。您甚至可以构建对嵌套属性名(如getValueByName(addressObj,"phoneNumbers.code"))的支持。对于更深入的层次,你可以使用递归:

  • 获取当前级别的字段-搜索当前段所需的字段,例如"phoneNumbers">
  • 获取该字段的值,并再次进入递归搜索下一个段,例如"代码">

如何组织你的进一步的代码取决于你的需求。可以有默认的"getter";以通用方式读取字段的值+ "自定义getter "覆盖特定类型的行为,如List<String>

问题更新后注意事项:以下是查找最大长度。如果需要找到具有最大长度的字符串,则必须更新代码,删除.length()并更新后续部分,同时考虑到。

要获得所有地址的最大城市长度,您可以这样做:

public int maxLengthAddressCity() {
return addresses.stream()
.mapToInt(address -> address.getCity().length())
.max();
}

假设Address类中的属性phoneNumbersList<PhoneNumber>类型而不是PhoneNumbers类型,以获得最大电话号码长度:

public int maxLengthPhoneNumber() {
return addresses.stream()
.flatMap(address -> address.getPhoneNumbers())
.mapToInt(phoneNumber -> phoneNumber.getPhone())
.max();
}

如果你需要一个泛型方法,你可以使用JsonPath库。将对象转换为json并使用json表达式,如:

// To get the list of city lengths, then use a max function to extract the maximum value 
$.addresses[*].city.length
// To get the list of city lengths, then use a max function to extract the maximum value 
$.addresses[*].phoneNumbers[*].phoneNumber.length

您可以使用https://jsonpath.com/工具在jsonPath上做一些实验,并在此链接查看java的jway库

最新更新