从map中获取,使用setter在对象中设置,但是对于太多字段?
问题
考虑一个具有很多字段的 Pojo 类。给出了一个HashMap。从地图中获取元素并设置在对象中(更新操作)。 需要考虑以下因素:
- HashMap 中的键名和对应的目标字段名不完全相同(参见示例)
- 如果映射中不存在某个键,则不更新相应的字段
- 如果存在键,则更新相应的字段(包括更新null)
- 不要担心 ClassCastException,映射值将始终以适当的类类型提供。
示例:
Map与Pojo对应关系:
HashMap中的key->对象 numberOfItems 中的字段名称
- -> 支付数量
- Amount ->价格
- adrLine1 ->房子
- adrLine2 ->道路
- adrLine3 ->区域
- adrLine4 -> city
- ...以及 100 个以上的
Pojo 类:
private static class MyObject{
private Integer quantity;
private Double price;
private String house;
private String road;
private String area;
private String city;
...
//getter-setters
}
一个好的旧的简单方法可以是:
private void someMethod(Map<String, Object> updateRequest, MyObject obj){
if(updateRequest.containsKey("numberOfItems")){
obj.setQuantity((Integer) updateRequest.get("numberOfItems"));
}
if(updateRequest.containsKey("paidAmount")){
obj.setPrice((Double) updateRequest.get("paidAmount"));
}
if(updateRequest.containsKey("adrLine1")){
obj.setHouse((String) updateRequest.get("adrLine1"));
}
if(updateRequest.containsKey("adrLine2")){
obj.setRoad((String) updateRequest.get("adrLine2"));
}
if(updateRequest.containsKey("adrLine3")){
obj.setArea((String) updateRequest.get("adrLine3"));
}
if(updateRequest.containsKey("adrLine4")){
obj.setCity((String) updateRequest.get("adrLine4"));
}
...
}
但正如您所看到的,这既不高效编码,也不具有良好的可维护性。
像这样的东西将是完美的:
Map<String, Object> updateRequest = //provided
MyObject obj = //provided
List.of(
Pair.of("numberOfItems", "quantity"),
Pair.of("paidAmount", "price"),
Pair.of("adrLine1", "house"),
Pair.of("adrLine2", "road"),
Pair.of("adrLine3", "area"),
Pair.of("adrLine4", "city")
).stream()
.filter(queryPair -> updateRequest.ContainsKey(queryPair.getKey()))
.forEach(queryPair -> obj. set ?? programmatically set field name ?? (updateRequest.get(queryPair.getKey())));
也请随意建议任何已经做到这一点的流行外部库。
Problem
Consider a Pojo class with a lot of fields. A HashMap is given. Get element from map and set in object (Update operation).
Following should be considered:
- The key name in HashMap and corresponding target field name are not exactly same (see example)
- If a key is not present in map, don't update corresponding field
- If key is present, update corresponding field (including updating with null)
- Do not worry about ClassCastException, map values will be provided with appropriate class type, always.
Example:
Map and Pojo correspondence:
key in HashMap - > field name in Object
- numberOfItems -> quantity
- paidAmount -> price
- adrLine1 -> house
- adrLine2 -> road
- adrLine3 -> area
- adrLine4 -> city
- ...and 100s more
Pojo class:
private static class MyObject{
private Integer quantity;
private Double price;
private String house;
private String road;
private String area;
private String city;
...
//getter-setters
}
A good old plain approach can be:
private void someMethod(Map<String, Object> updateRequest, MyObject obj){
if(updateRequest.containsKey("numberOfItems")){
obj.setQuantity((Integer) updateRequest.get("numberOfItems"));
}
if(updateRequest.containsKey("paidAmount")){
obj.setPrice((Double) updateRequest.get("paidAmount"));
}
if(updateRequest.containsKey("adrLine1")){
obj.setHouse((String) updateRequest.get("adrLine1"));
}
if(updateRequest.containsKey("adrLine2")){
obj.setRoad((String) updateRequest.get("adrLine2"));
}
if(updateRequest.containsKey("adrLine3")){
obj.setArea((String) updateRequest.get("adrLine3"));
}
if(updateRequest.containsKey("adrLine4")){
obj.setCity((String) updateRequest.get("adrLine4"));
}
...
}
But as you can see, this is neither efficient to code, nor comes with a good maintainability.
Something like this would be perfect:
Map<String, Object> updateRequest = //provided
MyObject obj = //provided
List.of(
Pair.of("numberOfItems", "quantity"),
Pair.of("paidAmount", "price"),
Pair.of("adrLine1", "house"),
Pair.of("adrLine2", "road"),
Pair.of("adrLine3", "area"),
Pair.of("adrLine4", "city")
).stream()
.filter(queryPair -> updateRequest.ContainsKey(queryPair.getKey()))
.forEach(queryPair -> obj. set ?? programmatically set field name ?? (updateRequest.get(queryPair.getKey())));
Also feel free to suggest any popular external library that already does this.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这是一个使用 lambda 来具体化 setter 的解决方案:
Here's a solution that uses lambdas to reify the setters:
您可以使用 ObjectMapper 然后合并两个映射。最后,您只需将地图转换为 MyObject。
请注意上面使用的重新映射函数。它仅设置来自 inputMap 的值。如果没有找到某个键的值,它将将该值保留在 myObjectMap 中。
You can convert your existing myObject instance to a map using ObjectMapper and then merge the two maps. Finally you just have to convert the map to MyObject.
Notice the remapping function used above. It only sets value from the inputMap. If no value found for a key, it will keep the value in myObjectMap.