从map中获取,使用setter在对象中设置,但是对于太多字段?

发布于 2025-01-16 09:49:45 字数 2266 浏览 1 评论 0原文

问题

考虑一个具有很多字段的 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

孤独岁月 2025-01-23 09:49:45

这是一个使用 lambda 来具体化 setter 的解决方案:

Map<String, Object> updateRequest = //provided
MyObject obj = //provided

Map<String, BiConsumer<MyObject, Object>> keyToSetter =
  Map.of(
    "numberOfItems", (o, v) -> o.setQuantity((Integer) v)
    // ...
  );

updateRequest.forEach((k, v) -> keyToSetter.get(k).accept(obj, v));


Here's a solution that uses lambdas to reify the setters:

Map<String, Object> updateRequest = //provided
MyObject obj = //provided

Map<String, BiConsumer<MyObject, Object>> keyToSetter =
  Map.of(
    "numberOfItems", (o, v) -> o.setQuantity((Integer) v)
    // ...
  );

updateRequest.forEach((k, v) -> keyToSetter.get(k).accept(obj, v));


围归者 2025-01-23 09:49:45

您可以使用 ObjectMapper 然后合并两个映射。最后,您只需将地图转换为 MyObject。

ObjectMapper mapper = new ObjectMapper();
Map<String,Object> myObjectMap = mapper.convertValue(obj, HashMap.class);
inputMap.forEach((k,v)-> myObjectMap.merge(k,v, (v1,v2)-> v2));
MyObject resultObject = mapper.convertValue(myObjectMap , MyObject.class);

请注意上面使用的重新映射函数。它仅设置来自 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.

ObjectMapper mapper = new ObjectMapper();
Map<String,Object> myObjectMap = mapper.convertValue(obj, HashMap.class);
inputMap.forEach((k,v)-> myObjectMap.merge(k,v, (v1,v2)-> v2));
MyObject resultObject = mapper.convertValue(myObjectMap , MyObject.class);

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文