Add Key and Value into an Priority Queue and Sort by Key in Java

Using Java-8

PriorityQueue<Map.Entry<String, Integer>> queue = new PriorityQueue<>(Map.Entry.comparingByValue(Comparator.reverseOrder()));

to add a new Entry

queue.offer(new AbstractMap.SimpleEntry<>("A", 10));

Problem

PriorityQueue can store a single object in it's each node. So what you are trying to do can not be done as it is.

But you can compose both objects in a single class and then use the PriorityQueue.

You would either need to supply a Comparator or rely on natural ordering by implementing Comparable interface.


Solution

  • Create a class which has String and int as it's members.

    public class Entry {
        private String key;
        private int value;
    
        // Constructors, getters etc.
    }
    
  • Implement Comparable interface and delegate comparison to String.

    public class Entry implements Comparable<Entry> {
        private String key;
        private int value;
    
        public Entry(String key, int value) {
            this.key = key;
            this.value = value;
        }
    
        // getters
    
        @Override
        public int compareTo(Entry other) {
            return this.getKey().compareTo(other.getKey());
        }
    }
    
  • Build the PriorityQueue using this class.

    PriorityQueue<Entry> q = new PriorityQueue<>();
    
  • Add elements as following.

    q.add(new Entry(strings.get(x), calculateStringValue(strings.get(x))));
    

Hope this helps.


Solution

public static List<String> pQSortStrings(List<String> strings) {    
    Queue<String> pq = new PriorityQueue<>((a, b) -> 
        calculateStringValue(b) - calculateStringValue(a));
    for (String str : strings) {
         pq.add(str);
    }
    return strings;
}

Explanation

I believe that the cleanest way to do this is to store Strings in your pq and use a small custom Comparator. In this case, we want to use calculateStringValue and the pq should return highest String values first. Therefore, make a pq of entries and use the following Comparator:

1   Queue<String> pq = new PriorityQueue<>(new Comparator<String>() {
2       @Override
3       public int compare(String a, String b) {
4           return calculateStringValue(b) - calculateStringValue(a);
5       }
6   });
7   for (String str : strings) {
8       pq.add(str);
9   }
10  return strings;

Simpler syntax for the Comparator, replacing lines 1 - 6, is:

Queue<String> pq = new PriorityQueue<>((a, b) -> 
    calculateStringValue(b) - calculateStringValue(a));

If you wanted to return smallest String values first, you could just switch the order around for a and b in the Comparator:

...new PriorityQueue<>((a, b) -> calculateStringValue(a) - calculateStringValue(b));

In general, the pattern a - b sorts by smallest first, and b - a sorts by largest values first.


Many good answers are already present but I am posting this answer because no one has used hashmap in their answers.


You can also make the priority Queue from HashMaps bellow is the example for the same. I am creating a max priority queue. Mind well here I am considering that your hashmap contains only one Entry

PriorityQueue<HashMap<Character, Integer>> pq = new PriorityQueue<>((a, b) -> {
        char keyInA = a.keySet().iterator().next(); // key of a
        char keyInB = b.keySet().iterator().next(); // key of b
        return b.get(keyInB) - a.get(keyInA);
    });

For Insertion of the value in the priority queue.

pq.add(new HashMap<>() {
            {
                put('a', 0);
            }
        });