I'm trying to use a priority queue in my code, and for some reason when I remove the objects, they aren't in order. Do you know what i"m doing wrong?
Here's my code:
the contructor:
recordedsong = new PriorityQueue<recordedNote>(50, new Comparator<recordedNote>()
{
public int compare(recordedNote n1, recordedNote n2)
{
long l = n1.rt()-n2.rt();
int i = (int)l;
return i;
}
});
where each recordedNotehas a long value that is returned my the method rt().
But when I call
while (!Song.isEmpty())
{
recordedNote temp = (recordedNote)Song.remove();
and then print temp.rt() for each one, all the numbers are out of order. And not just like reverse order, but all over the place, like 1103, 0, 500, 0, 220 orders like that.
Can you see if there's anything wrong with my contructor?
Thanks!
remove should work, and in fact it does work fine in a small example program that I created to help answer this question:
import java.util.Comparator;
import java.util.PriorityQueue;
public class TestPriorityQueue {
public static void main(String[] args) {
long[] noteTimes = {1103L, 0L, 500L, 0L, 220L, 1021212812012L};
PriorityQueue<RecordedNote> noteQueue = new PriorityQueue<RecordedNote>(10,
new Comparator<RecordedNote>() {
#Override
public int compare(RecordedNote o1, RecordedNote o2) {
Long time1 = o1.getTime();
Long time2 = o2.getTime();
// uses Long's built in compareTo method, so we
//don't have to worry as much about edge cases.
return time1.compareTo(time2);
}
});
for (int i = 0; i < noteTimes.length; i++) {
RecordedNote note = new RecordedNote(noteTimes[i]);
System.out.println(note);
noteQueue.add(note);
}
System.out.println();
while (noteQueue.size() > 0) {
System.out.println(noteQueue.remove());
}
}
}
class RecordedNote {
private long time;
public RecordedNote(long time) {
this.time = time;
}
public long getTime() {
return time;
}
#Override
public String toString() {
return "[Time: " + time + "]";
}
}
So this begs the question, why isn't it working for you? Myself, I don't see enough coherent code in your question to be able to answer this. We're not sure what is Song as I don't see this declared as a class or a variable, and I also don't see where you're using your PriorityQueue variable, recordedsong, anywhere. So I suggest you do the same thing as I: create a small compilable runnable program that we can run and modify and that demonstrates your problem, an http://sscce.org
I guess there is a possibility for i getting 0. So modify compare method so that it returns a positive value rather than the result.
Reading the API docs for PriorityQueue, it states the following:
The Iterator provided in method iterator() is not guaranteed to traverse the elements of the priority queue in any particular order. If you need ordered traversal, consider using Arrays.sort(pq.toArray()).
My guess is that remove() is not obligated to follow the natural ordering, either.
Related
This is my Code and I can't sort my LinkedList.
import java.util.Collections;
import java.util.LinkedList;
import org.omg.CosNaming.NameComponent;
public class Zug implements Comparable<Zug> {
private String abfahrtzeit;
private String zuggattung;
private int zugnummer;
private int fahrtzeit;
public Zug(String zeile) {
String[] teile = zeile.split(";");
this.abfahrtzeit = teile[0];
this.zuggattung = teile[1];
this.zugnummer = Integer.parseInt(teile[2]);
this.fahrtzeit = Integer.parseInt(teile[3]);
}
public String getAbfahrtzeit() {
return abfahrtzeit;
}
public String getZuggattung() {
return zuggattung;
}
public int getZugnummer() {
return zugnummer;
}
public int getFahrtzeit() {
return fahrtzeit;
}
public String toString() {
return this.abfahrtzeit + ";" + this.zuggattung + ";" + this.zugnummer + ";" + this.fahrtzeit;
}
// This is the Problem Block
#Override
public int compareTo (Zug z) {
String datei = "Zuege.dat";
LinkedList<Zug> ll = new LinkedList<Zug>();
Collections.sort( ll, new NameComponent() );
ll = getDaten(datei);
return this.fahrtzeit - z.getFahrtzeit();
}
// End Of Problem Block
private LinkedList<Zug> getDaten(String datei) {
return null;
}
}
As RealSkeptic and matoni write, you must not do anything other in the compareTo(Zug z) method than compare this to z - as the method name implies. compareTo(Zug z) is called by methods sorting a collection whenever they need to compare two elements of that collection. Loading lists of objects in that method doesn't make any sense.
The most simple implementation would be
#Override
public int compareTo(Zug z) {
return this.fahrtzeit - z.getFahrtzeit();
}
You may want to test your code with that implementation. Generate a few example Zug objects, add them to a List, sort that list using Collecitons.sort() and enjoy the result (or give us a meaningful error message).
Java Practices has an elaborate example on how to write a compareTo()-method.
Please note that this implementation is not consistent with equals() (as detailed in the javadoc).
Sorting by fahrzeit might not be the only way to sort your objects and probably should not be the natural order. You probably should implement a Comparator (e.g. FahrzeitComparator, AbfahrtzeitComparator ...) to be able to sort by different criteria. See this example.
Oh, and:
Rewriting your code with English variable names would allow more people to understand what your objects should represent...
I have a priority queue containing elements of a custom Type called Process. Each Process has 3 fields. I need to be able to retrieve a Process from my priority queue which has a particular value for one of its fields. How can I do this? poll() seems to always return the head of the queue.
Here is my code for the Process class:
package SPN;
public class Process implements Comparable<Process> {
#Override
public int compareTo(Process proc) {
//implement this
return 0;
}
private int arrive_time= 0;
private int burst_time = 0;
private int remain_time = 0;
public Process (int arr_time, int bur_time) {
this.arrive_time = arr_time;
this.burst_time = bur_time;
}
public int getArrTime() {return arrive_time;}
public int getBurTime() {return burst_time;}
public int getRemTime() {return remain_time;}
}
In another class I have created a priority queue called prq and added processes with different values for the fields. Don't worry about the incomplete code. I just can't add everything, coz it will be pages of code. Something like this:
p1 = new Process(2, 10);
prq.add(p1);
p2 = new Process(1, 8);
prq.add(p2);
p3 = new Process(0, 11);
prq.add(p3);
I need to be able to retrieve process p3 because it has the earliest arrive_time. How can I do this? The following seems to retrieve and remove only the head of the priority queue. Don't reccomend using a different data structure, as that does not really work. Has to be a priority queue, because I need to do further selecting based on the other fields as well.
Process current = prq.poll();
You should implement the compareTo method like this:
#Override
public int compareTo(Process proc) {
// this.arriveTime > proc.arriveTime --> >0
// this.arriveTime < proc.arriveTime --> <0
// this.arriveTime = proc.arriveTime --> 0
return this.arriveTime - proc.arriveTime;
}
This way the items that have smaller arriveTime will come first.
The reason I see here is because you have unfinished implementation of compareTo() method in Process class. Since its always zero being returned, the retrieval is in the order of insertion as its considering every object to be equal.
You could complete the implementation as below
public void compareTo(Process proc)
{
if (this.getArrTime() < proc.getArrTime()) {
return -1;
else if (this.getArrTime() > proc.getArrTime()) {
return 1;
else
return 0;
}
The purpose of a PriorityQueue is to have a collection of elements sorted by their priority. In your case processes that have arrived earliest have the highest priority. When adding an element to a PriorityQueue it will be compared to the other elements that are already in the queue and put in the right place.
Now I feel like we are still a little unclear about comparing objects, so here's a little explanation to that:
The compare method (which you have to implement because of the Comparator interface) always returns an int value, that is either < 0, equal to 0 or > 0.
equal to 0 means the two values compared are equal to each other
> 0 means that this is "greater" than the object given as a parameter
< 0 means that this is "smaller" than the object given as a parameter
Now as I already mentioned, the queue will compare the value you are trying to insert to the values that are already in the queue, according to your compare method.
So all you have to do is to properly implement your compare method, as Kiril Aleksandrov already explained.
Refer to the Oracle Docs https://docs.oracle.com/javase/8/docs/api/java/util/PriorityQueue.html
It is not necessary for Process class to implement Comparable<Process> interface:
public class Process {
private int arrive_time= 0;
private int burst_time = 0;
private int remain_time = 0;
public Process (int arr_time, int bur_time) {
this.arrive_time = arr_time;
this.burst_time = bur_time;
}
public int getArrTime() {return arrive_time;}
public int getBurTime() {return burst_time;}
public int getRemTime() {return remain_time;}
}
Your PriorityQueue which named prq can be initialized like:
PriorityQueue<Process> prq = new PriorityQueue<Process>(new Comparator<Process>() {
// arrive_time in ascending order
#Override
public int compare(Process p1, Process p2) {
return p1.arrive_time - p2.arrive_time;
}
});
Then:
Process p1 = new Process(2, 10);
prq.add(p1);
Process p2 = new Process(1, 8);
prq.add(p2);
Process p3 = new Process(0, 11);
prq.add(p3);
System.out.println(prq.poll().getArrTime()); // output is 0 (which means p3)
System.out.println(prq.poll().getArrTime()); // output is 1 (which means p2)
So I'm making a search algorithm. I'm using a queue to store all of my objects
This is how I initialised it
Queue<Node> queue = new LinkedList<Node>();
I want to compare a variable in each object and order to queue. My plan is to use a for loop to compare the first object with each of the other objects and whichever object has the lowest variable is sent to the front of the queue. Then move onto the next object and repeat the process. My issue is I'm not sure how to retrieve an object from the queue that isn't the first object in the queue....
You could do a for loop through the Queue:
for (Node n : queue) {
do stuff with n
}
However, you aren't going to be able to remove items from the middle of the queue. Might I suggest a structure like an ArrayList?
In my opinion the best way is to use PriorityQueue. You can specify implementation of Comparator interface that will impose how elements should be sorted inside of queue.
Here is an example:
Let's say that this is your Node class:
public class Node {
// this field will be used to sort in queue
private int value;
public Node(int value) {
this.value = value;
}
public int getValue() {
return value;
}
#Override
public String toString() {
return "My value is: " + value;
}
}
And here is example of adding Nodes into queue:
import java.util.PriorityQueue;
import java.util.Random;
public class QueueExample {
public static void main(String[] args) {
Random r = new Random();
// Priority queue with custom comparator
PriorityQueue<Node> queue = new PriorityQueue<Node>(10, new SampleNodeComparator());
// adding 100 nodes with random value
for(int i = 0; i < 100; ++i) {
queue.add( new Node(r.nextInt(1000)));
}
// nodes will be removed from queue in order given by comparator
while(queue.size() != 0) {
System.out.println(queue.remove());
}
}
}
And the most important part - implementation of our custom comparator
import java.util.Comparator;
// our comparator needs to implements Comparator interface
public class SampleNodeComparator implements Comparator<Node> {
#Override
public int compare(Node o1, Node o2) {
/*
value that should be return from compare method should follow rules:
if o1 == o2 - return 0
if o1 > o2 - return any positive value
if o1 < 02 - return any negative value
*/
return o1.getValue() - o2.getValue();
}
}
When you run main method from QueueExample class you will see on console that values are removed from queue sorted by Node.value value.
Use Queue<E>#peek () to retrieve an object without removing it.
Some example code:
import java.util.*;
class Example {
public static void main (String[] args) throws Exception {
Queue<String> list = new PriorityQueue<>();
{ // Initialize the Queue
list.add ("Hello ");
list.add ("Mrs. ");
list.add ("DoubtFire! ");
}
System.out.println (list);
// Iterating through the Queue
String element;
while ( (element = list.peek()) != null) {
if (element.equals ("Mrs. ")) {
System.out.println ("\"Mrs\" found!");
}
System.out.println (element);
list.remove (element);
}
System.out.println (list); // Empty by now...
}
}
Output:
[DoubtFire! , Mrs. , Hello ]
DoubtFire!
Hello
"Mrs" found!
Mrs.
[]
Queue interface does not guarantee any particular order while iterating or polling so theoretically this task is impossible to implement with Queue.
Seeing your response to my comment, I think that in your case, you should use the PriorityQueue because it does what you need without needing you to reinvent the wheel, which is usually not recommended.
By default, the priority queue will use the default implementation of the compareTo method. Assuming that you have a composite type, you have two options:
You can make your custom class implement the Comparabale interface and have your sorting logic there.
Alternatively, you could pass your own comparator:
PriorityQueue<..> p = new PriorityQueue<..>(5, new Comparator<..>()
{
#override
public int compare(.. type1, .. type2)
{
//comparison logic done here.
}
}
You can take a look at this short tutorial for more information.
I'm looking for some implementation of PQ in Java which allows iteration in PQ order - top element first, next one next etc. I tried using TreeSet (which implements NavigableSet) but it causes one problem. In my case:
I'm using Comparator for my objects
priority changes due to some external actions
if priority changes I know for which object, but I don't know it's previous priority
As a result to the last point - I can't find my element in TreeSet when I would like to update its priority:/
Do you happen to know: smart way to obey this? or some implementation of PQ that is iterable in "good" way? or should I create some linked data structure that will match objects with their positions in tree ?
UPDATE:
concurrency is not an issue
object can't be removed from TreeSet because it's priority changed so Comparator will evaluate differently and object won't be found in this data structure. Inserting is not a problem.
I can't use compareTo method as this priority is not proper way to compare those objects. That is why I need to use Comparator
POSSIBLE SOLUTION:
create class PrioritizedObject which will be compared by priority and keep my object
use map: my object -> PrioritizedObject
keep PrioritizedObject in some NavigableSet
I would use this map to remove objects from NavigableSet. And of course update it with new elements if I add something.
Problem is that I will have to wrap iterator from this NavigableSet to get iterator returning my objects.
Is there any better solution?
if priority changes I know for which object, but I don't know it's previous priority
You don't need to know its previous priority. All you have to do is remove it and re-insert it.
If concurrency is not an issue all you need to do is to reorder the tree right after updating an element's priority. If I understood the problem right, this sketch should suit you.
Example element:
public class Element implements Comparable<Element> {
private final Integer id;
private Integer priority;
public Element(Integer id, Integer priority) {
this.id = id;
this.priority = priority;
}
#Override
public String toString() {
return "Element{" + "id=" + id + ", priority=" + priority + '}';
}
public Integer getPriority() {
return priority;
}
public void setPriority(Integer priority) {
this.priority = priority;
}
#Override
public int compareTo(Element o) {
if (o == null) {
throw new NullPointerException();
}
return priority.compareTo(o.priority);
}
}
The sketch:
public class Tree {
public static TreeSet<Element> priorityQueue = new TreeSet<Element>();
public static void dump(TreeSet<Element> in) {
for (Element e : in) {
System.out.println(e);
}
}
public static void updatePriority(Element e, int newPriority) {
if (priorityQueue.remove(e)) {
e.setPriority(newPriority);
priorityQueue.add(e);
}
}
public static void main(String[] args) {
int id;
Element lastElement = null;
for (int i = 0;i < 10 ; i++) {
id = (int)(Math.random()*1000);
priorityQueue.add(lastElement = new Element(id, id));
}
dump(priorityQueue);
updatePriority(lastElement, 0);
System.out.println("updating "+lastElement+ " priority to 0");
dump(priorityQueue);
}
}
You update the element by removing it from the treeset, setting the new priority and then reinserting it. The complexity of the update operation with this scenario is 2*O(log(n)) = O(log(n))
UPDATE:
The best I could understand is: you have two criterias upon which you need to sort/index. When I had the same problem I used this approach but this is a very interesting approach that I strongly recommend reading.
I recommend ConcurrentSkipListSet instead of TreeSet since it's thread-safe. If you know the object whose priority is changing, you can call remove(objToChange), change its priority, then re-add it to the set.
Be very careful adding to a set any objects whose equals, hashcode, and compareTo methods depend on mutable fields.
Edit: I think any solution will end up looking like your PrioritizedObject which seems fine to me. If you want to iterate through your objects, use Map.keySet.
When return value is not of interest, is there any (even irrelevant in practice) difference between AtomicInteger.getAndIncrement() and AtomicInteger.incrementAndGet() methods, when return value is ignored?
I'm thinking of differences like which would be more idiomatic, as well as which would put less load in CPU caches getting synchronized, or anything else really, anything to help decide which one to use more rationally than tossing a coin.
Since no answer to the actual question has been given, here's my personal opinion based on the other answers (thanks, upvoted) and Java convention:
incrementAndGet()
is better, because method names should start with the verb describing the action, and intended action here is to increment only.
Starting with verb is the common Java convention, also described by official docs:
"Methods should be verbs, in mixed case with the first letter lowercase, with the first letter of each internal word capitalized."
The code is essentially the same so it does not matter:
public final int getAndIncrement() {
for (;;) {
int current = get();
int next = current + 1;
if (compareAndSet(current, next))
return current;
}
}
public final int incrementAndGet() {
for (;;) {
int current = get();
int next = current + 1;
if (compareAndSet(current, next))
return next;
}
}
No, there's no difference (if you don't care about the return value).
The code of those methods (in the OpenJDK) differs only in that one uses return next and the other uses return current.
Both use compareAndSet under the hood with the exact same algorithm. Both need to know both the old and the new value.
Just want to add to existing answers: there could be very small non-noticeable difference.
If you look at this implementation:
public final int getAndIncrement() {
return unsafe.getAndAddInt(this, valueOffset, 1);
}
public final int incrementAndGet() {
return unsafe.getAndAddInt(this, valueOffset, 1) + 1;
}
Note - both function call exactly the same function getAndAddInt, except +1 part, which means that in this implementation getAndIncrement is faster.
But, here is older implementation:
public final int getAndIncrement() {
for (;;) {
int current = get();
int next = current + 1;
if (compareAndSet(current, next))
return current;
}
}
public final int incrementAndGet() {
for (;;) {
int current = get();
int next = current + 1;
if (compareAndSet(current, next))
return next;
}
}
The only difference is return variable, so both functions perform exactly the same.
Here I am giving an example. Hope it will clear your doubt.
Suppose I have a variable i as
AtomicInteger i = new AtomicInteger();
In this case:
i.getAndIncrement() <==> i++;
And
i.incrementAndGet() <==> ++i;
Please have a look of the below programs
public class Test1
{
public static void main(String[] args)
{
AtomicInteger i = new AtomicInteger();
System.out.println(i.incrementAndGet());
System.out.println(i);
}
}
**output
1
1
======================================**
public class Test2
{
public static void main(String[] args)
{
AtomicInteger i = new AtomicInteger();
System.out.println(i.getAndIncrement());
System.out.println(i);
}
}
**output
0
1
-------------**
Comment:
1) In the class Test1, incrementAndGet() will first increment the i value and then print.
2) In the class Test2, getAndIncrement() will first print the i value and then increment.
That's all.