【问题标题】:Efficiently Merge two ArrayLists of Maps高效合并 Map 的两个 ArrayList
【发布时间】:2019-09-17 00:24:11
【问题描述】:

面临一个挑战,想出一种有效的方法来合并两个 Map 的 ArrayList。

地图是这样的:

{Username=User1, Role=Admin}

所以一个列表看起来像这样:

List1 =  [{Username=User1, Role=Admin},{Username=User2, Role=Auditor}]

等等。

还有一个列表:

List 2 = [{Username=User1, Role=Integrator},{Username=User2, Role=Manager}]

注意:用户在不同的列表中有不同的角色。

我想结束的是:

MergedList = [{Username=User1, Role=[Admin,Integrator]},{Username=User2, Role=[Auditor,Manager}]

另外说明:实际列表有50,000张地图,每张地图有20个条目!!只是在这里尽量保持简单。

以下是我尝试过的东西。但是失败了。

试过putAll。 试过merge

尝试了我在另一篇文章中找到的东西

map2.forEach((k, v) -> map3.merge(k, v, String::concat));

【问题讨论】:

    标签: java performance dictionary merge hashmap


    【解决方案1】:

    关于性能和海量数据,我建议你避免使用(虽然它本身很快)和Map::merge方法。

    在这里你必须坚持使用接近 JVM 级别的结构,for-loops 是你的朋友,这是我知道的最简单的方法:

    final Map<String, Set<String>> newMap = new HashMap<>();
    
    for (Map<String, String> map: list) {                        // iterate the List<Map>
        for (Entry<String, String> entry: map.entrySet()) {      // iterate the entries
            final String key = entry.getKey();                   // get the entry's key
            newMap.computeIfAbsent(key, k -> new HashSet<>());   // compute a new pair
            newMap.get(key).add(entry.getValue());               // add a value in any case
        }
    }
    

    Set 防止重复值。

    此解决方案采用以下数据结构。细微的变化很容易应用于上述解决方案。

    List<Map<String, String>> list = new ArrayList<>();
    
    Map<String, String> map1 = new HashMap<>();
    map1.put("User1", "Admin");
    map1.put("User2", "Auditor");
    
    Map<String, String> map2 = new HashMap<>();
    map2.put("User1", "Integrator");
    map2.put("User2", "Manager");
    map2.put("User3", "Coffee machine");
    
    list.add(map1);
    list.add(map2);
    

    【讨论】:

    • 太棒了.. 这肯定有助于@Nikolas 我刚刚转换为 Beanshell(前面提到过)并输出为地图列表。它运行了 4 秒 :) 非常感谢您的帮助!
    【解决方案2】:

    您可以使用 Java Streams 来实现:

    Map<String, List<String>> result = Stream.concat(users1.stream(), users2.stream())
            .collect(Collectors.groupingBy(m -> m.get("Username"), Collectors.mapping(m -> m.get("Role"), Collectors.toList())));
    

    这会将所有用户分组并收集他们的角色。

    结果将是:

    {User1=[Admin, Integrator], User2=[Auditor, Manager]}
    

    【讨论】:

    • 恐怕在关注性能时使用Collectors.groupingBy 不是最好的主意。
    • @Nikolas 为什么这是个坏主意?您还可以使用并行流以获得更好的性能。
    猜你喜欢
    • 2013-09-30
    • 2019-04-20
    • 1970-01-01
    • 2011-05-27
    • 2017-04-11
    • 1970-01-01
    • 2017-08-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多