Search code examples
javahashmapqueueclasscastexceptioncomparable

Why can't I compare two Hashmaps


In my code I need to have a Queue of two values that I store as key and value in a HashMap. But when I put the maps in a Queue I get this exception:

Exception in thread "main" java.lang.ClassCastException: java.util.HashMap cannot be cast to java.lang.Comparable
        at java.util.PriorityQueue.siftUpComparable(Unknown Source)
        at java.util.PriorityQueue.siftUp(Unknown Source)
        at java.util.PriorityQueue.offer(Unknown Source)
        at java.util.PriorityQueue.add(Unknown Source)
        at com.n2s.StringsPractise.Prime.primeCheck(Prime.java:32)
        at com.n2s.StringsPractise.Randomizer.main(Randomizer.java:22)

Here is a description of what my code does and then the code itself:

Randomizer‘s job is to generate a series of positive random integers and send those to Prime via a distributed queue of integers. Primes job is to receive the integers and calculate whether the integer is a prime or not and return the answer to Randomizer via a distributed queue ( just a java Queue implementation , no need to implement JMS etc ) that contains the original number and a Boolean; which Randomizer will print to system out.

Randomizer Class:

    public class Randomizer{

    static Queue<Integer> q = new PriorityQueue<Integer>(); 
    public static Queue<Integer> randomGenerate(){
        int num = 0;
        Random rand = new Random();
        for(int k = 0; k < 10; k++){
        num = rand.nextInt(Integer.MAX_VALUE);
        q.add(num);
        num = 0;
        }
        return q;
    }
    public static void main(String[] args){
        Queue<HashMap<Integer, String>> outQ = Prime.primeCheck(randomGenerate());
        System.out.println(outQ);}
    }
}

Prime Class:

public class Prime{
    Randomizer rn = new Randomizer();
    static HashMap<Integer, String> map = new HashMap<Integer, String>();
    static Queue<HashMap<Integer, String>> primeQ = new PriorityQueue<HashMap<Integer, String>>();

    public static Queue<HashMap<Integer, String>> primeCheck(Queue<Integer> q){
            boolean flag = false;
            Iterator<Integer> itr = q.iterator();
                while(itr.hasNext()){
                    int item = (int) itr.next();
                    int srt = (int) Math.sqrt((double) item);
                    if (item==1) {
                            flag = true;
                        } else{
                        for(int i=2;i<=srt;i++){

                            if(item % i == 0) flag = false;          
                        }
                        flag =  true;
                        }
                    if(flag == true)
                    map.put(item, "Prime");
                    else map.put(item, "Not Prime");

                    primeQ.add(map);

                }
                return primeQ;              
            }
}

Solution

  • Your problem is that the PriorityQueue tries to compare two HashMaps against each other, but they have no meaningful way of being compared.

    I recommend you use a value holder class like this:

    public class Value implements Comparable<Value> {
    
        int item;
        boolean isPrime;
    
        public Value(int item, boolean isPrime) {
            this.item = item;
            this.isPrime = isPrime;
        }
    
        @Override
        public int compareTo(Value o) {
            if (o == null) {
                return 1;
            }
            return this.item - o.item;
        }
    
        @Override
        public String toString() {
            return "Value{" + "item=" + item + ", isPrime=" + isPrime + '}';
        }
    }
    

    Then your whole code would look like this: (I took the liberty of cleaning it up and fixing your logic problem as mentioned in my comment to your question)

    public class DLH {
    
        public static void main(String[] args) {
            Randomizer ran = new Randomizer();
            Queue<Value> outQ = new Prime().primeCheck(ran.randomGenerate());
            System.out.println(outQ);
        }
    
        private static class Value implements Comparable<Value> {
    
            int item;
            boolean isPrime;
    
            public Value(int item, boolean isPrime) {
                this.item = item;
                this.isPrime = isPrime;
            }
    
            @Override
            public int compareTo(Value o) {
                if (o == null) {
                    return 1;
                }
                return this.item - o.item;
            }
    
            @Override
            public String toString() {
                return "Value{" + "item=" + item + ", isPrime=" + isPrime + '}';
            }
        }
    
        private static class Prime {
    
            Queue<Value> primeQ = new PriorityQueue<>();
    
            public Queue<Value> primeCheck(Queue<Integer> q) {
                boolean flag;
                Iterator<Integer> itr = q.iterator();
                while (itr.hasNext()) {
                    Value val;
                    int item = (int) itr.next();
                    int srt = (int) Math.sqrt((double) item);
                    if (item == 1) {
                        flag = true;
                    } else {
                        flag = true;
                        for (int i = 2; i <= srt; i++) {
    
                            if (item % i == 0) {
                                flag = false;
                            }
                        }
                    }
                    val = new Value(item, flag);
    
                    primeQ.add(val);
    
                }
                return primeQ;
            }
        }
    
        private static class Randomizer {
    
            public Queue<Integer> randomGenerate() {
                Queue<Integer> q = new PriorityQueue<>();
                int num;
                Random rand = new Random();
                for (int k = 0; k < 10; k++) {
                    num = rand.nextInt(Integer.MAX_VALUE);
                    q.add(num);
                }
                return q;
            }
        }
    }