如何获取哈希映射(HashMap)中的前3个最大值?

huangapple go评论81阅读模式
英文:

How to get the 3 highest values in a HashMap?

问题

以下是翻译好的内容:

我有一个哈希映射,如下所示:

HashMap<String, Integer> hm = new HashMap<String, Integer>();
hm.put("a", 1);
hm.put("b", 12);
hm.put("c", 53);
hm.put("d", 2);
hm.put("e", 17);
hm.put("f", 8);
hm.put("g", 8);

我要如何获取具有最高三个值的键?这将返回:

"c", "e", "b"

谢谢。

英文:

I have a hashmap which is the following:

    HashMap&lt;String, Integer&gt; hm = new HashMap&lt;String, Integer&gt;;
    hm.put(&quot;a&quot;, 1);
    hm.put(&quot;b&quot;, 12);
    hm.put(&quot;c&quot;, 53);
    hm.put(&quot;d&quot;, 2);
    hm.put(&quot;e&quot;, 17);
    hm.put(&quot;f&quot;, 8);
    hm.put(&quot;g&quot;, 8);

How would I get the keys which have the 3 highest values? So it would return:

    &quot;c&quot;, &quot;e&quot;, &quot;b&quot;

Thanks.

答案1

得分: 12

List<String> keys = hm.entrySet().stream().sorted(Map.Entry.<String, Integer>comparingByValue().reversed()).limit(3).map(Map.Entry::getKey).collect(Collectors.toList());
英文:

My solution, sort by values and get top 3 and return key list.

List&lt;String&gt; keys = hm.entrySet().stream().sorted(Map.Entry.&lt;String, Integer&gt;comparingByValue().reversed()).limit(3).map(Map.Entry::getKey).collect(Collectors.toList());

Hope it helps

答案2

得分: 4

这段代码是要描述一个性能更好但难以阅读的实现方式。如果你了解PriorityQueue的工作原理,这将变得相对简单:它在任何给定时间点只保留n + 1个元素。随着元素的添加,最小的元素逐个被移除。

当这个过程完成后,我们将元素插入到一个数组中,但是顺序是反向的(因为PriorityQueue只保持其头部有序,或者头部始终根据Comparator是最大值/最小值)。

你甚至可以将其泛化,或者使用流创建一个自定义的收集器来实现这一功能。

英文:

This is a lot harder to read, but will perform a lot better:

 public static List&lt;String&gt; firstN(Map&lt;String, Integer&gt; map, int n) {
    PriorityQueue&lt;Entry&lt;String, Integer&gt;&gt; pq = new PriorityQueue&lt;&gt;(
        n + 1, Map.Entry.comparingByValue()
    );

    int bound = n + 1;
    for (Entry&lt;String, Integer&gt; en : map.entrySet()) {
        pq.offer(en);
        if (pq.size() == bound) {
            pq.poll();
        }
    }

    int i = n;
    String[] array = new String[n];
    while (--i &gt;= 0) {
        array[i] = pq.remove().getKey();
    }
    return Arrays.asList(array);
}

If you know how a PriorityQueue works, this is rather trivial: it keeps only n + 1 elements at any given point in time. As elements are being added, the smallest element is removed, one by one.

When this is done, we insert elements into an array, but in reverse order (because a PriorityQueue keeps sorted only its head or the head is always max/min according to the Comparator).

You can even make this generic, or create a custom collector with streams for this.

答案3

得分: 1

这是我的看法:这只追踪TreeSet中排名靠前的n个项目。

import java.util.*;
import java.util.stream.Collectors;

public class TopN {
    public static <E> Collection<E> topN(Iterable<E> values, Comparator<? super E> comparator, int n) {
        NavigableSet<E> result = new TreeSet<>(comparator.reversed());
        for (E value : values) {
            result.add(value);
            if (result.size() > n) {
                result.remove(result.last());
            }
        }
        return result;
    }

    public static void main(String[] args) {
        Map<String, Integer> hm = Map.of(
                "a", 1,
                "b", 12,
                "c", 53,
                "d", 2,
                "e", 17,
                "f", 8,
                "g", 8);

        List<String> result = topN(hm.entrySet(), Map.Entry.comparingByValue(), 3)
                .stream()
                .map(Map.Entry::getKey)
                .collect(Collectors.toList());
        System.out.println(result);
    }
}

最终输出为[c, e, b]

英文:

Here's my take on it: This keeps track of only the top n items in a TreeSet.

import java.util.*;
import java.util.stream.Collectors;

public class TopN {
    public static &lt;E&gt; Collection&lt;E&gt; topN(Iterable&lt;E&gt; values, Comparator&lt;? super E&gt; comparator, int n) {
        NavigableSet&lt;E&gt; result = new TreeSet&lt;&gt;(comparator.reversed());
        for (E value : values) {
            result.add(value);
            if (result.size() &gt; n) {
                result.remove(result.last());
            }
        }
        return result;
    }

    public static void main(String[] args) {
        Map&lt;String, Integer&gt; hm = Map.of(
                &quot;a&quot;, 1,
                &quot;b&quot;, 12,
                &quot;c&quot;, 53,
                &quot;d&quot;, 2,
                &quot;e&quot;, 17,
                &quot;f&quot;, 8,
                &quot;g&quot;, 8);

        List&lt;String&gt; result = topN(hm.entrySet(), Map.Entry.comparingByValue(), 3)
                .stream()
                .map(Map.Entry::getKey)
                .collect(Collectors.toList());
        System.out.println(result);
    }
}

The final output is [c, e, b]

huangapple
  • 本文由 发表于 2020年5月29日 10:31:07
  • 转载请务必保留本文链接:https://go.coder-hub.com/62077736.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定