Java的Counter Counter替代品

nik*_*sdi 9 python java sorting data-structures

我一直在使用Python中的Counter()数据结构作为键值存储,允许我使用most_common方法根据其值对对象进行排序.更多信息在这里.

Java语言是否有类似的数据结构?例如,我已经看到许多相关的答案专注于通过数据结构对HashMapsTreeMaps进行排序,最初并未为此目的定义.在我的情况下,我通常需要保留对象的计数器,然后选择最常见的或具有最高分数的那些(前N个查询).但是,我很难,因为我需要插入HashMap然后排序或使用多个数据结构.

aro*_*ire 8

这里:

Counter类与其他语言的bag或multisets类似.

Java没有Multiset类或模拟类.Guava有一个MultiSet系列,可以完全满足您的需求.

在纯Java中,您可以使用Map和新的合并方法:

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

counts.merge("Test", 1, Integer::sum);
counts.merge("Test", 1, Integer::sum);
counts.merge("Other", 1, Integer::sum);
counts.merge("Other", 1, Integer::sum);
counts.merge("Other", 1, Integer::sum);

System.out.println(counts.getOrDefault("Test", 0));
System.out.println(counts.getOrDefault("Other", 0));
System.out.println(counts.getOrDefault("Another", 0));
Run Code Online (Sandbox Code Playgroud)

输出:

2
3
0
Run Code Online (Sandbox Code Playgroud)

您可以在几行代码中将此行为包装在一个类中:

public class Counter<T> {
    final Map<T, Integer> counts = new HashMap<>();

    public void add(T t) {
        counts.merge(t, 1, Integer::sum);
    }

    public int count(T t) {
        return counts.getOrDefault(t, 0);
    }
}
Run Code Online (Sandbox Code Playgroud)

并像这样使用它:

final Counter<String> counts = new Counter<>();

counts.add("Test");
counts.add("Test");
counts.add("Other");
counts.add("Other");
counts.add("Other");

System.out.println(counts.count("Test"));
System.out.println(counts.count("Other"));
System.out.println(counts.count("Another"));
Run Code Online (Sandbox Code Playgroud)

输出:

2
3
0
Run Code Online (Sandbox Code Playgroud)


Old*_*eon 5

这是一个看起来像它实现了足够的类Counter来做你想做的事情。

static class Counter<T> {

    final ConcurrentMap<T, Integer> counts = new ConcurrentHashMap<>();

    public void put(T it) {
        add(it, 1);
    }

    public void add(T it, int v) {
        counts.merge(it, v, Integer::sum);
    }

    public List<T> mostCommon(int n) {
        return counts.entrySet().stream()
                // Sort by value.
                .sorted((e1, e2) -> Integer.compare(e2.getValue(), e1.getValue()))
                // Top n.
                .limit(n)
                // Keys only.
                .map(e -> e.getKey())
                // As a list.
                .collect(Collectors.toList());
    }
}

public void test() {
    Counter<String> c = new Counter<>();
    String[] numbers = {"Zero", "One", "Two", "Three", "Four", "Five", "Six"};
    for (int i = 0; i < numbers.length; i++) {
        c.add(numbers[i], i);
    }
    System.out.println(c.mostCommon(3));
}
Run Code Online (Sandbox Code Playgroud)

它使用 Java 8 功能。

  • 我登录只是为了对此点赞 - 谢谢。我还注意到“mostCommon”方法实际上返回最不常见的元素。编辑被拒绝,我不太清楚为什么。但我至少想为使用此功能的任何人留下一条注释 - 将 `Integer.compare(e1.getValue(), e2.getValue())` 与 `Integer.compare(e2.getValue(), e1.getValue() ))` 为了获得最常见的元素 (2认同)