Reputation: 787
I know what is a priority queue and I know how to add strings/integers to it. But now I want to add functions to it. (If this makes sense??) . I am not ready to change the return type of any function.
I want to know how can I go about doing that? I made a raw type priority queue
PriorityQueue prq = new PriorityQueue ();
prg.offer(login());
Now, I am not a coding genius, I am also learning. So I wanted to see if its possible. If it isn't possible are there any alternate solutions?
My pop() function will just run the function which got pop'd. Most of my functions are void.
An idea I got: Should I just insert string and do a switch statement depending on which string I pop()???
Upvotes: 0
Views: 1025
Reputation: 34628
In general, it is possible to do something like this, but I would recommend thinking it through. And the implementation is a bit unwieldy.
First, you're working with a priority queue. This means that you want to receive the things that were added to it by order of their priority. A priority queue is an ordered collection. And in order to do that, the items you put inside it must be Comparable
. This is why a priority queue of String or Integer work. Both of them are Comparable
- if you have two Strings in the queue, it's easy to tell which comes first, as Strings have a natural order. Nevertheless it must be said that in real life, you normally don't assign things String priorities. A priority queue is supposed to represent which things are more urgent to deal with, and which are less so. So usually priorities are more likely to be implemented as some sort of number or Enum.
So in addition to putting a function in the queue, you also need to assign it a priority when you put it in the queue, and that will tell whoever is reading from the queue which functions it's more urgent to perform. He'll simply get them by order of priority.
So we need to define some sort of object that will encapsulate both a function and a priority:
public final class PrioritizedPerformer implements Comparable<PrioritizedPerformer> {
/**
* Actor interface. Represents a way to run a function.
*/
public interface Actor {
void perform();
}
/**
* Available priorities
*/
public enum Priority { URGENT, HIGH, MEDIUM, LOW };
private Priority priority;
private Actor actor;
/**
* Constructor that allows creating PrioritizedPerformer objects with a given priority and actor.
*
* @param priority Priority of this object when placed in a priority queue.
* @param actor Actor representing a function to be performed.
*/
public PrioritizedPerformer(Priority priority, Actor actor) {
// Don't allow null priorities, this will cause problems in priority queues.
if ( priority == null ) {
throw new IllegalArgumentException("Must provide valid priority");
}
this.priority = priority;
// Don't allow null actors. The action has to be available.
if ( actor == null ) {
throw new IllegalArgumentException("Must provide valid actor");
}
this.actor = actor;
}
/* Allows prioritizing one PrioritizedPerformer over another.
*
* @see java.lang.Comparable#compareTo(java.lang.Object)
*/
@Override
public int compareTo(PrioritizedPerformer o) {
return priority.compareTo(o.priority);
}
/**
* Perform whatever action the actor represents.
*/
public void perform() {
actor.perform();
}
}
Now that we have that, we can put objects of this type into the priority queue:
PriorityQueue<PrioritizedPerformer> queue = new PriorityQueue<PrioritizedPerformer>();
queue.offer(new PrioritizedPerformer(
PrioritizedPerformer.Priority.HIGH,
new PrioritizedPerformer.Actor() {
public void perform() {
login();
}
}));
queue.offer(new PrioritizedPerformer(
PrioritizedPerformer.Priority.LOW,
new PrioritizedPerformer.Actor() {
public void perform() {
quit();
}
}));
queue.offer(new PrioritizedPerformer(
PrioritizedPerformer.Priority.URGENT,
new PrioritizedPerformer.Actor() {
public void perform() {
returnThree();
}
}));
What we do here is construct each PrioritizedPerformer
object with a given Priority
and an anonymous Actor
which performs the function we wanted it to perform.
Now we can run:
queue.remove().perform();
This will remove the highest priority object from the queue, and run its perform()
method, which calls its internal Actor
's perform()
method. In this case, it will take the one whose priority is URGENT
, which happens to run the function returnThree()
.
So this will do what you asked for. And yet I recommend against it. It can only perform functions that have no parameters (or just call a specific function with predetermined parameters). You can't pass it something like Math.sqrt
, because when you need to perform it, there is no way for you to pass a number to that function.
What this leads to is using global-scope fields to pass data to the various functions instead of parameters. This in turn leads to readability issues, lack of encapsulation, which means your parameters may be changed by methods you didn't intend to change them. It's all sorts of bad. In addition, in this particular setting, how will you know which parameters to set in the global scope if you don't know which function you're going to run next?
Upvotes: 0
Reputation: 9648
What you are currently doing is putting the return value of the function in the queue. So the function executes and then the value that it produces is put into the queue. Instead you could have a queue of Runnable
s and then call the run()
method on them:
PriorityQueue<Runnable> queue = new PriorityQueue<Runnable>();
queue.offer( new Runnable() { public void run() { login(); } );
queue.remove().run();
Or, if using Java 8:
PriorityQueue<Runnable> queue = new PriorityQueue<>();
queue.offer(() -> login(););
Upvotes: -1
Reputation: 330
You cannot use the function as an argument to priority queue (In java), but you can use return value of the function, as long as return type of the function matches the required argument.
The type of the argument in offer() is specified by generics. Here is code example.
public static int login(){
return 0;
}
public static void main (String[] args){
PriorityQueue<Integer> prq = new PriorityQueue<Integer>();
prg.offer(login());
}
You can then change Integer to whatever is return type of your function login().
Upvotes: 0