Как получить 3 самых высоких значения в HashMap? - PullRequest
5 голосов
/ 29 мая 2020

У меня есть следующая хэш-карта:

    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"

Спасибо.

Ответы [ 3 ]

8 голосов
/ 29 мая 2020

Мое решение, отсортируйте по значениям и получите 3 верхних и верните список ключей.

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

Надеюсь, это поможет

4 голосов
/ 29 мая 2020

Это намного труднее читать, но он будет работать намного лучше:

 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);
}

Если вы знаете, как работает PriorityQueue, это довольно тривиально: он сохраняет только n + 1 элементов в в любой момент времени. По мере добавления элементов самые маленькие элементы удаляются один за другим.

Когда это будет сделано, мы вставляем элементы в массив, но в обратном порядке (потому что PriorityQueue сохраняет сортировку только в своей голове, или голова всегда имеет значение max / min в соответствии с Comparator).

Вы даже можете сделать этот общий c или создать собственный сборщик с потоками для этого.

1 голос
/ 01 июня 2020

Вот мое мнение: он отслеживает только первые n элементов в TreeSet.

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]

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...