Search code examples
javacopypriority-queue

Copy of a PriorityQueue without Interfere with the original PriorityQueue


I am trying to copy a PriorityQueue object.

My goal is to change some object of my Copy without modifying my original PriorityQueue

In order to do so I did a copy of my PriorityQueue and I delete a value of my copy, but when I check if my PriorityQueue is stil the same, unfortunately the original PriorityQueue was changed as well... If you have any suggestion it will be welcome.

Please find an example of what I tried :

public class PQExample
{
    public int id;
    public int price;
    public String name;
    public long date;

        public PQExample(int id, int price, String name, long time)
        {
            this.id = id;
            this.price = price;
            this.name = name;
            this.date = time;
        }

        public static void main(String[] args)
        {
            PriorityQueueComparator pqc = new PriorityQueueComparator();
            PriorityQueue<PQExample> PQ = new PriorityQueue<PQExample>(pqc);
            int setID = 1000;
            int setDate = 0;
            PQ.add(new PQExample(setID++, 24 , "Mat", setDate++));
            PQ.add(new PQExample(setID++, 25 , "Tommy", setDate++));
            PQ.add(new PQExample(setID++, 22 , "Kate", setDate++));
            PQ.add(new PQExample(setID++, 26 , "Mary", setDate++));
            PQ.add(new PQExample(setID++, 24 , "Ronny", setDate++));
            PQExample valueToDel = new PQExample(1000,22,"Mat",0);

            PriorityQueue<PQExample> PQCopy = new PriorityQueue<PQExample>();
            PQCopy = PQ;

            //Now I want to delete only in PQCopy and not in PQ    
            PQCopy.remove(valueToDel);

            //Unfortunately Mat was deleted of both objects : PQ and PQCopy...
            for (int i = 0; i < 4; i++) {
                System.out.println("Queue in: " + i + " is " + PQ.peek().name + " with the price of " + PQ.peek().price);
                PQ.poll();
            }
        }
@Override
public boolean equals(Object o)
{
    if (o instanceof PQExample)
    {
        PQExample pqExample = (PQExample)o;
        return id == pqExample.id;
    }
    return false;
}


class PriorityQueueComparator implements Comparator<PQExample>
{
    @Override
    public int compare(PQExample o1, PQExample o2) {
        if (o1.price < o2.price){return 1;}else if (o1.price > o2.price){return -1;}
        else
        {if (o1.date<o2.date){return -1;}else{return 1;}}
    }
}

Solution

  • What you are doing here:

    PriorityQueue<PQExample> PQCopy = new PriorityQueue<PQExample>();
    PQCopy = PQ;
    

    Is:

    1. Create a new object and store its reference in PQCopy.
    2. Make PQCopy reference the same object as PQ

    You need to create a new PriorityQueue object with the copy constructor instead:

    PriorityQueue<PQExample> PQCopy = new PriorityQueue<>(PQ);
    

    As you can read here:

    Creates a PriorityQueue containing the elements in the specified collection...

    Be aware however that, although it copies the collection into a new one, the referenced objects are the same. This implies that if you change the contained objects' attributes, these changes will be noticed in the elements of both collections.

    EDIT

        PriorityQueue<Integer> PQ= new PriorityQueue<Integer>();
        PQ.add(3);
        PQ.add(4);
        PriorityQueue<Integer> PQCopy = new PriorityQueue<>(PQ);
        PQCopy.remove();
        
        for(Integer i: PQ)
        {
            System.out.println(i);
        }
        
        for(Integer i: PQCopy)
        {
            System.out.println(i);
        }
    

    This other example shows how changes to the contained objects will affect the copied list too, if the contained objects are mutable:

       class CTest implements Comparable<CTest> {
            public CTest(int v) {
                this.v = v;
            }
            Integer v;
    
            @Override
            public int compareTo(CTest o) {
                return this.v.compareTo(o.v);
            }
        }
    
        PriorityQueue<CTest> PQ= new PriorityQueue<CTest>();
        PQ.add(new CTest(3));
        PQ.add(new CTest(4));
        PriorityQueue<CTest> PQCopy = new PriorityQueue<>(PQ);
        PQCopy.iterator().next().v = new Integer(6);
        
        for(CTest i: PQ)
        {
            System.out.println(i.v);
        }
        
        for(CTest i: PQCopy)
        {
            System.out.println(i.v);
        }