【问题标题】:Count occurrences of value in a map计算地图中值的出现次数
【发布时间】:2017-06-12 13:16:25
【问题描述】:

我有以下类型的地图:

private HashMap<Integer, HashMap<String, Object>> entireMap;

密钥从 1 到 n。整个地图中的子地图属于以下类型:

HashMap<String, Object> subMap = new HashMap<String, Object>();

整个地图的每个键都包含这个 subMap(以及更多):

subMap.put("user_name", usid[1]);

所以我最后有这样的东西:

{1 {"user_name" = "Arthur", "otherKeys = ..."}}
{2 {"user_name" = "Bela", "otherKeys = ..."}}
{3 {"user_name" = "Ceasar", "otherKeys = ..."}}
{4 {"user_name" = "Ceasar", "otherKeys = ..."}}
{5 {"user_name" = "Bela", "otherKeys = ..."}}
{6 {"user_name" = "Bela", "otherKeys = ..."}}

现在我想计算一个用户名在整个地图中的最大出现次数,在这种情况下它将是 3(bela 出现 3 次)。

我该怎么做?

【问题讨论】:

  • 但是在 subMap 中,你不能有重复的键..
  • 对不起,我刚刚注意到您的示例的每条记录都是@整个地图级别。

标签: java hashmap counting


【解决方案1】:

如果您不想使用 java 8 功能,则可以通过简单地遍历地图来实现。

Map<String, Integer> resultMap = new HashMap<String, Integer>();

for (int key : entireMap.keySet()) {
    String userName = (String) entireMap.get(key).get("user_name");

    if (resultMap.containsKey(userName)) {
        resultMap.put(userName, resultMap.get(userName) + 1);
    } else {
        resultMap.put(userName, 1);
    }
}

System.out.println(resultMap);

输出:

{亚瑟=1,凯撒=2,贝拉=3}

【讨论】:

  • resultMap.get(userName) + 1 将抛出 NullPointerException。你可能想做resultMap.getOrDefault(userName, 0)。或者,在 Java 8 之前,类似 Integer count = resultMap.get(userName); resultMap.put(count != null ? count.intValue() + 1 : 1);.
  • @VGR 他的resultMap.containsKey(userName) 条件不会阻止这种情况发生吗?
  • @phatfingers 是的,确实如此。我不知道为什么我没有看到。
  • @VGR :如果您对我投了反对票并且您认为我的回答是正确的,那么您能否回复您的投票?这将帮助我建立自己的声誉。
  • 除非您以某种方式编辑您的问题,否则系统将不允许我更改我的投票。我建议将第一行改为Map&lt;String, Integer&gt; resultMap,因为变量类型应该引用一个契约(Map)而不是一个实现(HashMap)。
【解决方案2】:

这是一个实现示例。

注意:不要在生产代码中使用这样的地图初始化!

    HashMap<Integer, HashMap<String, Object>> entireMap = new HashMap<>();
    entireMap.put(1, new HashMap<String, Object>() {{
        put("user_name", "Arthur");
        put("other_key1", "val");
        put("other_key2", "val");
    }});
    entireMap.put(2, new HashMap<String, Object>() {{
        put("user_name", "Bela");
        put("other_key2", "val");
    }});
    entireMap.put(3, new HashMap<String, Object>() {{
        put("user_name", "Ceasar");
    }});
    entireMap.put(4, new HashMap<String, Object>() {{
        put("user_name", "Ceasar");
    }});
    entireMap.put(5, new HashMap<String, Object>() {{
        put("user_name", "Bela");
    }});
    entireMap.put(6, new HashMap<String, Object>() {{
        put("user_name", "Bela");
    }});

    Map<Object, Long> result = entireMap
            .values()
            .stream()
            .map(map -> map.get("user_name"))
            .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));

    System.out.println(result);

    Long max = Collections.max(result.values());
    System.out.println(max);

输出:

{Ceasar=2, Arthur=1, Bela=3}
3

【讨论】:

  • 或者没有map()调用:Map&lt;Object,Long&gt; counts = entireMap.values() .stream() .collect(Collectors.groupingBy(v -&gt; v.get("user_name"), Collectors.counting()));
  • @Eran 是的,当然。但我更喜欢将每个操作的职责分开
【解决方案3】:

这是使用 Java 8 功能但没有流的一种方法:

Map<String, Long> counts = new HashMap<>();
entireMap.forEach((k, v) ->
    counts.merge(v.get("user_name"), 1L, Long::sum));

counts 映射中,您将获得每个用户的计数。然后你可以找到最大值的条目:

Entry<String, Long> max = Collections.max(
    counts.entrySet(),
    Map.Entry.comparingByValue());

【讨论】:

    【解决方案4】:

    在 Java 7 或更低版本中,您可以使用 Guava MultiSet:

    List<Object> names = new ArrayList<>();
    for (HashMap<String, Object> outerMap : entireMap.values()) {
        names.add(outerMap.get("user_name"));
    }
    
    HashMultiset<Object> objects = HashMultiset.create(names);
    
    objects.forEachEntry((name, count) -> System.out.println(name + " -> " + count));
    

    结果:

    Ceasar -> 2
    Arthur -> 1
    Bela -> 3
    

    【讨论】:

      猜你喜欢
      • 2012-10-20
      • 1970-01-01
      • 1970-01-01
      • 2011-05-08
      • 2019-07-26
      • 2010-11-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多