简体   繁体   English

如何获得 HashMap 中的 3 个最高值?

[英]How to get the 3 highest values in a HashMap?

I have a hashmap which is the following:我有一个 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);

How would I get the keys which have the 3 highest values?我将如何获得具有 3 个最高值的键? So it would return:所以它会返回:

    "c", "e", "b"

Thanks.谢谢。

My solution, sort by values and get top 3 and return key list.我的解决方案,按值排序并获得前 3 名并返回键列表。

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

Hope it helps希望能帮助到你

This is a lot harder to read, but will perform a lot better:这很难阅读,但会表现得更好:

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

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

    int i = n;
    String[] array = new String[n];
    while (--i >= 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.如果您知道PriorityQueue是如何工作的,那么这很简单:它在任何给定时间点只保留n + 1元素。 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 ).完成后,我们将元素插入到数组中,但顺序相反(因为PriorityQueue仅对其头部进行排序,或者根据Comparator头部始终为最大/最小值)。

You can even make this generic, or create a custom collector with streams for this.您甚至可以将其设为通用,或为此创建带有流的自定义收集器。

Here's my take on it: This keeps track of only the top n items in a TreeSet.这是我的看法:它只跟踪 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);
    }
}

The final output is [c, e, b]最终的 output 是[c, e, b]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM