如何计算重复列表中实体的出现次数?

时间:2018-10-13 15:15:19

标签: java algorithm data-structures

我有一个5位数组合的列表(可能有重复:双打,三联等)。我需要计算每个组合出现在该列表中的频率。实际上,组合是具有相应位设置的唯一BitSet(如果组合包含数字5,则设置第5位,依此类推)

列表

12345
34578
12345
98710
12345

我会得到

12345 -> 3
34578 -> 1
98710 -> 1

是否准备好解决此任务?就像我将12345字符串添加到此数据结构三次,然后查询12345(分别为Bitset对象),并返回3作为出现次数。我想到了Apache Commons Frequency类,但这无济于事。

3 个答案:

答案 0 :(得分:6)

如果您正在寻找一种现成的数据结构,该结构可以存储个带有计数的元素,那么 Guava's Multiset 就是这么做的。

如果您只需要将列表转换为计数图,请继续阅读。

您可以使用Java 8 Streams API在单个语句中将列表转换为计数映射:

final var list = List.of("12345", "34578", "12345", "98710", "12345");

final var counts = list.stream()
    .collect(Collectors.toMap(
        Function.identity(), // Map keys are list elements
        value -> 1, // Map values are counts, a single item counts "1"
        (count1, count2) -> count1 + count2 // On duplicate keys, counts are added
    ));

在后台,此解决方案使用哈希映射(要计数的元素)作为数据结构。

您也可以使用groupingBy收集器,如Peter Lawrey的建议:

final var list = List.of("12345", "34578", "12345", "98710", "12345");

final var counts = list.stream()
    .collect(Collectors.groupingBy(
        Function.identity(), // Group the elements by equality relation
        Collectors.counting() // Map values are counts of elements in the equality groups
    ));

有时(边学习边)通过“手动”实现所有内容以理解算法是有益的。因此,这里的版本没有Java 8好东西,例如流,收集器和新的地图方法,例如Map.compute()

final List<Stream> list = List.of("12345", "34578", "12345", "98710", "12345"); // Use ArrayList if you're below Java 9

final Map<String, Integer> counts = new HashMap<>();
for (final String item : list) {
    // Note: I'm deliberately NOT using Map.compute() here
    // to demonstrate how to do everything "manually"
    Integer count = counts.get(item);
    if (count == null) {
        count = 0;
    }
    counts.put(item, count + 1);
}

答案 1 :(得分:0)

假设您的列表是字符串(如果不是,则可能需要一个“比较器”)。循环遍历整个列表,将元素添加到HashMap和自己的计数器中;但是在此之前,请检查相关元素是否存在,并相应地更新计数器。

最终,Java流也可以提供帮助。

答案 2 :(得分:0)

您可以使用简单的Collections.frequency方法来做到这一点。

import java.util.List;
import static java.util.Collections.frequency;

List list = List.of("12345", "34578", "12345", "98710", "12345");
System.out.println( frequency(list, "12345") );