统计列表中每个项目出现的次数

6
我有一组重复值的流式输入。我可以使用任何数据结构,但必须计算每个元素出现的次数。假设我有以下移动电话供应商列表:
Apple
Nokia
Samsung
Apple
LG
Nokia
HTC
Android
Apple
Nokia
Nokia
Apple
Samsung
我必须构建一个数据结构,最好是一个映射,其中包含以下详细信息:
Apple,4
Nokia,4
Samsung,2
LG,1
Android,1
我不确定这是否是最优解。是否有比这更好的解决方案?事实上,我还没有将上述内容编写为代码。因此,更好的代码也会有所帮助。

“计算列表项”似乎具有误导性。 - Tom
7个回答

5

是的,我会使用一个Map<String, Integer>。我会将add包装在类似这样的代码中:

private static void incrementValue(Map<String, Integer> counters, String toAdd) {
    Integer currValue = counters.get(toAdd);
    if (currValue == null)
        counters.put(toAdd, 1);
    else
        counters.put(toAdd, currValue+1);
}

或者不使用泛型:

private static void incrementValue(Map counters, String toAdd) {
    Integer currValue = (Integer) counters.get(toAdd);
    if (currValue == null)
        counters.put(toAdd, 1);
    else
        counters.put(toAdd, currValue+1);
}

一个小信息...我不能使用泛型,因为我必须使用Java 1.4。 - Harish

4

由于问题提出者提到无法使用泛型,因为目标平台是Java 1.4,因此可以使用不使用泛型的Apache Commons Collections

pjp的回答提到可以使用Bag。

事实证明,Apache Commons Collections有一个Bag,它有一个getCount方法,它将返回添加到Bag中的某个对象的计数。

以下是一个示例,add一些Integer对象到HashBag中,并计算Bag包含的每个Integer对象的数量:

Bag b = new HashBag();

b.add(Integer.valueOf(1));
b.add(Integer.valueOf(2));
b.add(Integer.valueOf(2));
b.add(Integer.valueOf(3));

System.out.println("Count for 1: " + b.getCount(Integer.valueOf(1)));
System.out.println("Count for 2: " + b.getCount(Integer.valueOf(2)));
System.out.println("Count for 3: " + b.getCount(Integer.valueOf(3)));

以下是结果:

1 的计数:1
2 的计数:2
3 的计数:1

(需要添加免责声明,此代码实际上是在Java 6上编译和运行的,但我相信我只使用了自Java 5以前存在的功能。)


太棒了...我想投票给你,但我还没有声望...感谢回复。 - Harish
1
+1,这应该是被采纳的答案。唯一可能不这样做的原因是害怕使用外部库(我自己也有这种担心)。 - Michael Myers

1
数据从哪里来?如果是数据库,您可以在后端查询中使用group by轻松完成此操作。

0

看起来使用地图是个好主意。可以直接访问 :)

键:元素 值:出现次数或元素在列表中的索引列表。


0
除了已经发布的解决方案之外,我首先想到的是制作一个“代码-值”表格,并使用代码对列表进行编码。这将非常节省空间。

0

太好了,但如何获取计数? - Harish
请注意,Google Collections需要Java 5。除此之外,这比我的答案更容易实现。 - Michael Myers
你可以通过遍历entrySet()来获取计数。如果你想将计数流出,你可以扩展实现以在计数发生变化时通知监听器。 - pjp

0
你可以使用Java 8中提供的Map.getOrDefault来实现这个功能。就是这么简单。
Map<String, Integer> map = new HashMap<>();

for (String s : List.of("Apple", "Samsung", "Apple", "...")) {
  map.put(s, map.getOrDefault(s, 0) + 1);
}
  • getOrDefault方法返回指定键s映射的值,如果该映射不包含键s,则返回0
  • 然后将返回的值增加1
  • 将键值对添加到映射中。

或者,使用Java 8流 - 结合groupingBycounting收集器:

Map<String, Long> map =
    List.of("Apple", "Samsung", "Apple", "...").stream()
        .collect(Collectors.groupingBy(s -> s, Collectors.counting()));

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接