我有一个POJO对象,字段很少,字符串列表。我们必须使用pojo的字段值创建一个对象列表,其顺序与字符串列表的顺序完全相同。现在我在使用pojo getters调用list.add时循环使用String -
列表public class ResultSet {
private String field1;
private String field2;
private String field3;
private String field4;
public List<Object> populateResultList(List<String> list) {
List<Object> resultSet = new ArrayList<>();
for (String filedName : list) {
if ("Field1".equalsIgnoreCase(filedName)) {
resultSet.add(getField1());
} else if ("Field2".equalsIgnoreCase(filedName)) {
resultSet.add(getField2());
} else if ("Field3".equalsIgnoreCase(filedName)) {
resultSet.add(getField3());
} else if ("Field4".equalsIgnoreCase(filedName)) {
resultSet.add(getField4());
}
}
return resultSet;
}
public String getField1() {
return field1;
}
public String getField2() {
return field2;
}
public String getField3() {
return field3;
}
public String getField4() {
return field4;
}
}
有没有更好的方法来实现它作为很多样板代码。
答案 0 :(得分:4)
您可以使用普通Java 8 Stream API执行此操作。您可以在fieldName
字符串和Function<ResultSet, Object>
之间定义返回与fieldName
关联的值的映射。使用函数具有以下优势:您可以将其简化为method reference,如ResultSet::getField1
等效于以下lambda表达式:
Function<ResultSet, Object> f = resultSet -> resultSet.getField1();
通过这种方式,您可以像这样定义映射映射:
private static final Map<String, Function<ResultSet, Object>> mappings = new HashMap<String, Function<ResultSet, Object>>() {{
put("field1", ResultSet::getField1);
put("field2", ResultSet::getField2);
put("field3", ResultSet::getField3);
put("field4", ResultSet::getField4);
}};
然后您的populateResultList
方法可能如下所示:
public List<Object> populateResultList(List<String> list) {
return list.stream()
.map(fieldName -> mappings.getOrDefault(fieldName.toLowerCase(), it -> null).apply(this))
.filter(Objects::nonNull)
.collect(Collectors.toList());
}
这里发生的事情是输入fieldName
中的每个List<String>
我们采用mappings
地图中定义的映射器,或者如果给定{的映射器,我们会返回it -> null
的映射器{1}}未定义。调用fieldName
会过滤掉结果列表中的所有空元素。
在这里你可以找到 Demo
.filter(Objects::nonNull)
我希望它有所帮助。
答案 1 :(得分:1)
您可以使用java库vavr并将代码缩减为:
public List<String> populateResultList(List<String> list) {
return list.stream()
.map(v -> Match(v).of(
Case($("Field1"), getField1()),
Case($("Field2"), getField2()),
Case($("Field3"), getField3()),
Case($("Field4"), getField4())))
.collect(toList());
}
您可以将Match表达式视为返回结果的Switch语句。返回的结果就是我们将列表的值映射到。
答案 2 :(得分:1)
如果您不介意一点反思技巧,并且不想将字段名称硬编码为方法参考,则以下方法有效,如果您向ResultSet
添加更多字段,则可以更加维护未来。
public class Main {
private static Map<String, Method> getterMap;
static {
try {
getterMap = Arrays.stream(Introspector.getBeanInfo(ResultSet.class).getPropertyDescriptors())
.filter(pd -> pd.getReadMethod() != null && !"class".equals(pd.getName()))
.collect(Collectors.toMap(pd -> pd.getName().toLowerCase(), PropertyDescriptor::getReadMethod));
} catch (IntrospectionException e) {
getterMap = Collections.emptyMap();
}
}
public static void main(String[] args) {
ResultSet resultSet = new ResultSet("lorem", "ipsum", "dolor", "sit amet");
List<String> list = Arrays.asList("field1", "Field4", "Field3", "Field2", "field9");
List<String> list1 = list.stream()
.map(String::toLowerCase)
.filter(getterMap::containsKey)
.map(getterMap::get)
.map(getter -> invokeGetter(getter, resultSet))
.collect(Collectors.toList());
System.out.println(list1);
}
private static String invokeGetter(Method getter, ResultSet rs) {
try {
return getter.invoke(rs).toString();
} catch (ReflectiveOperationException e) {
throw new RuntimeException(e);
}
}
}