【问题标题】:How to combine two different Map in java?如何在java中组合两个不同的Map?
【发布时间】:2019-01-02 19:17:01
【问题描述】:

我关注了很多这样的链接Merging two Maps,但仍然无法解决问题。

我有两张地图List<Map<String, Object>> - 这张地图包含acc_num, parent_acc_num, crte_dt, rnwl_dt, userid 等,其他地图 包含acc_numisActive(这是第一张地图的更细化)。

我想创建/组合这两个地图并创建包含acc_num, parent_acc_num, crte_dt, rnwl_dt, userid + isActive 详细信息的最终地图。

我该怎么做?

以下是示例数据。唯一的问题是两者都是地图列表,如何迭代另一个?

{CRTE_DT=2017-06-22, USER_ID=ABC, ACC_NUM=9449, RNWL_DT=2017-06-22, PARENT_ACC_NO=9449}

{ACC_NUM=9449, IS_ACTIVE=false}

另一个查询: 如果以下可行,则可能不需要进行计算

我有以下使用 12c 的 Oracle 查询,如果

  1. 如果 CreatedDate + 30 天 > Sysdate 然后显示列具有 true ---> In Trail
  2. 如果 CreatedDate + 30 天 超出跟踪期

"select cust.acc_num,third.parent_acc_id,cust.crte_dt,cust.updated_dt,cust.crte_user_id from CUST_ACCT cust,ThirdParty_third 第三个" + "其中 cust.updated_dt 为空且 cust.CRTE_DT

【问题讨论】:

  • 两张地图还是两张清单?你想如何合并acc_num?你试过什么?你被困在哪里了?
  • 是的,使用帐号,两者都是地图列表
  • 对于每个地图值对象都是不同的,如果您想合并地图,则需要一种新类型的对象来保存以前的数据。向我们展示这些对象。另外,列表是否包含 2 个元素?如果是这样,你为什么需要一个列表?

标签: java java-8


【解决方案1】:

假设您的列表仅包含两个地图并且它们都是可变的。当且仅当第二个映射的映射ACC_NUM 等于第一个映射时,您可以做的是将第二个映射的所有映射添加到第一个映射。

final List<Map<String, Object>> maps = ...;

if (Optional.ofNullable(map.get(1).get("ACC_NUM")).filter(acc_num -> acc_num.equals(map.get(0).get("ACC_NUM"))).isPresent())
{
    map.get(0).putAll(map.get(1));
}

编辑

final List<Map<String, Object>> l1 = ...;
final List<Map<String, Object>> l2 = ...;

final List<Map<String, Object>> result = l1.stream()
    .map(map ->
    {
      final Map<String, Object> r = new HashMap<>(map);
      l2.stream()
          .filter(map2 -> Objects.equals(map.get("ACC_NUM"), map2.get("ACC_NUM")))
          .findFirst()
          .map(map2 -> map2.get("IS_ACTIVE"))
          .ifPresent(is_active -> map.put("IS_ACTIVE", is_active));
      return r;
    })
    .collect(Collectors.toList());

【讨论】:

  • @Prateek 你可以检查我的编辑,它部分等同于Aomine's answer
  • @marsouf - 非常感谢。 +1,您是否也可以在没有 java 8 的情况下发布答案?
【解决方案2】:

这是一种解决方法:

List<Map<String, Object>> map3 = new ArrayList<>();
l1.forEach(map -> {
      // clone the map to avoid mutating existing maps
     Map<String, Object> temp = new HashMap<>(map);

     // get the corresponding match in the second list
     Optional<Object> value = l2.stream()
             .filter(m -> m.containsValue(map.get("ACC_NUM")))
             .findFirst().map(c -> c.get("IS_ACTIVE"));


     temp.put("IS_ACTIVE", value.get());  // insert the new entry
     map3.add(temp); // add the new map to the accumulator
});

这实质上是枚举l1(第一个列表)中的每个映射,并将整个映射克隆到一个新映射实例中,然后简单地将一个新条目插入到这个新映射中,其中键是"IS_ACTIVE",值是什么我们在l2(第二个列表)中找到。

此解决方案假定l2 中始终存在相应的匹配项,因此在Optional&lt;T&gt; 结果上调用get()。但是,如果不是这种情况,那么您可以使用 Optional#orElse 提供默认值,或者如果找不到该值,您根本不想将条目添加到地图中,请考虑在之前使用 Optional#isPresent添加到地图。

此外,我建议您通过 Guide To Java 8 Optional 熟悉可选 API,当然还有 java documentation!

【讨论】:

  • 我喜欢它使用新的流 API :-) - 但我认为这可能是 O(n*m),而我的老式的应该只有 O(m +n) ...
【解决方案3】:

我会创建一个Map&lt;Integer,Map&lt;String,Object&gt;&gt; 来帮助解决问题。 "acct_num" 是两个地图通用的键,因此您将使用它来匹配它们。
步骤:

  • 遍历第一个列表,使用其 acc_num 作为键将每个元素添加到地图中。
  • 遍历第二个列表,使用每个元素的 acct_num 值在 map 中找到匹配的元素,然后将第二个列表中的 "is_active" 对添加到您刚刚在 map 中找到的值。
  • 从您的帮助地图中获取values(),您将获得一个包含合并值的地图列表。

代码如下所示:

a = [CRTE_DT:"2017-06-22", USER_ID:"ABC", ACC_NUM:9449, RNWL_DT:"2017-06-22", PARENT_ACC_NO:9449]
b = [ACC_NUM:9449, IS_ACTIVE:false]
list1 = [a]
list2 = [b]
c = new HashMap<Integer,Map<String,Object>>()
for ( Map<String,Object> r : list1 ) { 
    c.put(r.get("ACC_NUM"),r) 
}
for (Map<String,Object> r : list2 ) { 
    d = c.get(r.get("ACC_NUM")); 
    if (d != null) d.putAll(r); 
}

groovy:000> c
===> {9449={CRTE_DT=2017-06-22, USER_ID=ABC, ACC_NUM=9449, RNWL_DT=2017-06-22, PARENT_ACC_NO=9449, IS_ACTIVE=false}}

【讨论】:

    猜你喜欢
    • 2017-07-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-09
    相关资源
    最近更新 更多