How to get 5 highest values from a hashmap?

前端 未结 6 1103
慢半拍i
慢半拍i 2021-02-06 14:49

I have a Hashmap that links a zipcodes stored as keys and population stored as values in a hashmap.

The hashmap contains around 33k entries.

I\'m trying to get t

相关标签:
6条回答
  • 2021-02-06 14:58

    Putting the entries of such a set into a list and sorting it is one option. But 33k elements is a number where the O(n*log(n)) complexity of sorting might already have a noticable performance impact.

    One apporach would be to employ the PriorityQueue that nr4bt already mentioned (I wrote this snippet while he answered). It basically inserts all elements into a PriorityQueue that is sorted according to the values of the map entries.

    import java.util.ArrayList;
    import java.util.Comparator;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    import java.util.Map.Entry;
    import java.util.PriorityQueue;
    
    public class GreatestOfMap
    {
        public static void main(String[] args)
        {
            Map<String, Integer> map = new HashMap<String, Integer>();
    
            map.put("zip000", 1234);
            map.put("zip001", 2345);
            map.put("zip002", 3456);
            map.put("zip003", 4567);
            map.put("zip004", 5678);
            map.put("zip005", 6789);
            map.put("zip006", 123);
            map.put("zip007", 234);
            map.put("zip008", 456);
            map.put("zip009", 567);
            map.put("zip010", 7890);
            map.put("zip011", 678);
            map.put("zip012", 789);
            map.put("zip013", 890);
    
            int n = 5;
            List<Entry<String, Integer>> greatest = findGreatest(map, 5);
            System.out.println("Top "+n+" entries:");
            for (Entry<String, Integer> entry : greatest)
            {
                System.out.println(entry);
            }
        }
    
        private static <K, V extends Comparable<? super V>> List<Entry<K, V>> 
            findGreatest(Map<K, V> map, int n)
        {
            Comparator<? super Entry<K, V>> comparator = 
                new Comparator<Entry<K, V>>()
            {
                @Override
                public int compare(Entry<K, V> e0, Entry<K, V> e1)
                {
                    V v0 = e0.getValue();
                    V v1 = e1.getValue();
                    return v0.compareTo(v1);
                }
            };
            PriorityQueue<Entry<K, V>> highest = 
                new PriorityQueue<Entry<K,V>>(n, comparator);
            for (Entry<K, V> entry : map.entrySet())
            {
                highest.offer(entry);
                while (highest.size() > n)
                {
                    highest.poll();
                }
            }
    
            List<Entry<K, V>> result = new ArrayList<Map.Entry<K,V>>();
            while (highest.size() > 0)
            {
                result.add(highest.poll());
            }
            return result;
        }
    }
    
    0 讨论(0)
  • 2021-02-06 15:00

    PriorityQueue would help too, and also a nice topic about how to get top k from a list, you can check this link

    PriorityQueue<Integer> p = new PriorityQueue<Integer>(5);
    
    int[] a = new int[]{3,5,10,1,23,42,66,1333,545,110};
    
    for (int i : a){
        p.add(i);
        if (p.size() > 5){
            p.poll();
        }
    }
    
    //output will be highest 5, [42, 66, 110, 1333, 545]
    

    You can have O(n log(k)) time complexity // k is your top value count.

    0 讨论(0)
  • 2021-02-06 15:06

    How would you do this without a computer, with just a piece of paper and a pencil? Pretend you had a stack of index cards that had numbers on them, and it was your job to find the 5 highest numbers. How would you do that? Write down steps that somebody else could follow to achieve the goal, and when you have those steps written out, you'll have an algorithm that you can start thinking about implementing with code.

    You say that a single maximum is easy, so do it exactly like you would with a single maximum, but keep track of the five maximums instead. An array of maximums might be helpful here.

    0 讨论(0)
  • 2021-02-06 15:09

    Try this, using standard methods and assuming that the population count is stored as Integers in the HashMap:

    List<Integer> list = new ArrayList<Integer>(zipCodePop.values());
    Collections.sort(list, Collections.reverseOrder());
    List<Integer> top5 = list.subList(0, 5);
    
    0 讨论(0)
  • 2021-02-06 15:16

    This is something i made and hopefully provides you something that you want to use.

    public class TopsCollection { 
    
    private static Map<String, Integer> collectors = new HashMap<>();
    
    public TopsCollection() {
    }
    
    public void add(String playerName, int score) {
        collectors.put(playerName, score);
    }
    
    public void clearCollectors() {
        synchronized (collectors) {
            collectors.clear();
        }
    }
    
    public List<Map.Entry<String, Integer>> getTops() {
        return collectors.entrySet().stream().sorted(comparing(Map.Entry::getValue, reverseOrder())).limit(5).collect(toList());
    }
    
    public int getTopByName(String name) {
        for (int i = 0; i < getTops().size(); i++) {
            if (getTops().get(i).getKey().contains(name)) {
                return i;
            }
        }
        return 0;
    }
    

    getTopByName allows you to get the top place of the specified name.

    0 讨论(0)
  • 2021-02-06 15:17

    public class CheckHighiestValue { public static void main(String... s) {

        HashMap<String, Integer> map = new HashMap<String, Integer>();
    
        map.put("first", 10000);
        map.put("second", 20000);
        map.put("third", 300);
        map.put("fourth", 800012);
        map.put("fifth", 5000);
        map.put("sixth", 30012);
        map.put("seventh", 1234);
        map.put("eighth", 45321);
        map.put("nineth", 5678);
    
        Set<Entry<String, Integer>> set = map.entrySet();
    
        List<Entry<String, Integer>> list = new ArrayList<Entry<String, Integer>>(
                set);
    
        Collections.sort(list, new Comparator<Map.Entry<String, Integer>>() {
    
            @Override
            public int compare(Entry<String, Integer> o1,
                    Entry<String, Integer> o2) {
    
                return o2.getValue().compareTo(o1.getValue());
            }
    
        });
        System.out.println(list.subList(0, 5));
    }
    

    }

    0 讨论(0)
提交回复
热议问题