Hello Im a bit lost n the priority queues and comparator.
I dont really see how to make a comparator in java
So what I have is giving me a error and what I have read is no help to me
http://www.tutorialspoint.com/java/java_using_comparator.htm
This post game me some ideas but Im still stuck on how to do it
How do I use a PriorityQueue?
What i have is a class that creates an object with a priority, arrival time, and finish time.
I also have a number of priority queues to place them into. When i start I place them into the arrival queue to sort them and then see which one came in first and place that into the queue one. But when I try to add a second one to the arrival queue it fails and throws an exception.
What I want to do first is to add all the processes to the arrival queue and then sort them so the one with the smallest arrival time will be the first one out of the arrival queue and into the queue one.
Thanks for any help with this
//the comparator
Comparator<Integer> comparator = new Comparator();
//priority queues
//only needs 10 elements to hold
PriorityQueue one = new PriorityQueue(10, comparator);
PriorityQueue two = new PriorityQueue(10, comparator);
PriorityQueue three = new PriorityQueue(10, comparator);
PriorityQueue four = new PriorityQueue(10, comparator);
PriorityQueue arrival = new PriorityQueue(10, comparator);
//put all processes in arrival queue
arrival.add(p1);
arrival.add(p2);
arrival.add(p3);
arrival.add(p4);
arrival.add(p5);
arrival.add(p6);
arrival.add(p7);
arrival.add(p8);
arrival.add(p9);
arrival.add(p10);
Let's look at how you're defining Comparator, because at the moment I don't think what you've written would even compile.
Comparator is an interface, meaning that you need to define a class that implements it. That is, you need to define a class that has concrete implementations of the methods described by the interface. Here, there's only one method you need to worry about - compare. (The interface also defines equals, but that's an odd choice since it's equal to the one on Object and so every class will implement this by default...)
The compare method takes two objects of the target type, and decides which one of them comes "before" the other. It returns:
a negative integer, zero, or a positive integer as the
first argument is less than, equal to, or greater than the
second.
So - you want to compare objects of whatever the class of your p1, p2 instances are (I'll call it MyClass). That means that you have to define a class:
class MyComparator implements Comparator<MyClass> {
public int compare(MyClass a, MyClass b) {
// TODO
}
}
We know that the compare method should return a value depending on which of the MyClass arguments comes before the other one. You've said in your question that the one that comes first, is the one that has the smallest (i.e. earliest?) arrival time.
This is actually very easy, because that's the so-called natural ordering on java.util.Date objects - so you can just compare their arrival times against each other directly, as the result of that comparison is the same as the overall comparison.
Therefore the implementation of compare can simply be (assuming a sensibly-named accessor method):
public int compare(MyClass a, MyClass b) {
return a.getStartTime().compareTo(b.getStartTime());
}
And there you go! You've just defined your own comparator, that will sort MyClass objects by start time ascending. You can use it in the priority queues similarly to what you have already:
Comparator<MyClass> comparator = new MyComparator();
PriorityQueue<MyClass> arrival = new PriorityQueue<MyClass>(10, comparator);
Related
I took a look at the code in this thread: https://codereview.stackexchange.com/questions/98105/priority-stack-in-java
This implements a PriorityStack using the object and the priority. I need an implementation where you only add the object to the PriorityStack, and using the Comparable interface you can define which attribute should be prioritized.
For example:
I have a list of dogs:
name = "Skip", age = 4
name = "Gregory", age = 3
name = "Ziggy", age = 4
In the Dog object I would implement the Comparable interface with:
public int compareTo(Dog other) {
if(other == null) {
return -1;
}
return this.age - other.age;
}
How can I use this to prioritize my PriorityStack?
The result of this should be the youngest dog first, and then the other 2 dogs based on First In Last Out
Consider that a stack can be viewed as a priority queue that prioritizes based on the time the item was enqueued. It wouldn't be as efficient as what we typically call a stack, but it would be LIFO.
That PriorityStack can more easily be implemented with a PriorityQueue, and probably a whole lot more efficiently. The only catch is that you'll either need to add a time field to your Dog class, or wrap the Dog object in another class that has a time field. I'd favor the latter: call it PQDog. And of course you'll need a custom comparer.
The time field doesn't have to be the actual time something was enqueued. It could be an integer if you make sure to increment it for each item enqueued. Provided you're not going to enqueue more than 2 billion items over the lifetime of the queue. Come to think of it, if you start the sequence at Integer.MinValue (or whatever it's called in Java), you could extend that range to 4 billion.
The idea is that you'd define the class:
class PQDog {
int sequenceNumber;
Dog dog;
}
I'm not really a Java programmer, so don't expect the code below to compile without trouble. But I think it's enough to point you in the right direction.
When you want to put a Dog in the queue, you wrap it in a PQDog object and add the new sequence number. Imagine you have a static variable called QueueSequence that you increment every time just before enqueueing.
PriorityQueue dogQueue = new PriorityQueue<PQDog>();
static int QueueSequence = 0;
// and to add something to the queue
PQDog newDog = new PQDog(QueueSequence++, Dog);
dogQueue.add(newDog);
And of course when you pop from the queue you'll have to unwrap the Dog.
It seems like your ordering requirement is "By ascending age and descending time". So your comparer would be something like:
public int compareTo(PQDog other) {
if(other == null) {
return -1;
}
// sort younger dogs first
if (this.Dog.age < other.Dog.age) return -1;
if (this.Dog.age > other.Dog.age) return 1;
// ages are the same, so compare enqueue time
if (this.sequenceNumber > other.sequenceNumber) return -1;
if (this.sequenceNumber < other.sequenceNumber) return 1;
// Probably should raise an exception here
// If you have two entries with the same sequence number,
// something has gone horribly wrong.
return 0;
}
Or, if the Dog class already has a CompareTo that compares by age, you'd change the above code to:
if (this.Dog.CompareTo(other.Dog) == 0) return;
// and then compare the sequenceNumbers if the
// dogs' ages aren't equal.
Seems silly to me to introduce an incomplete and un-vetted custom PriorityStack data structure when you can solve your problem using the standard Java PriorityQueue, a custom comparer, and a few lines of interface code.
As an aside, you shouldn't in general use return a - b in a Comparable. Imagine what happens when a is equal to the minimum integer (or sufficiently negative, anyway) and b is a large enough positive number. Integer overflow (actually underflow, but same thing) rears its ugly head. The result will be a positive number, erroneously indicating that a is greater than b.
Yes, I realize that in this particular case you won't run into that issue. At least, I don't think you have any dogs that are negative 2 billion years old. But much of what we do as programmers relies on patterns and common practice. One should get in the habit of writing bulletproof code when practical. No telling what somebody will do with your code after you write it. Perhaps some beginner is looking for a Comparable implementation, runs across your code, copies it to his program with that return a - b in there. All the unit tests and integration tests pass, the code goes into production, and four months later something breaks.
Not that I'm talking from experience or anything . . .
(Edited answer after the clarifications given in the comments)
In the PriorityStack in the link, it takes two values and stored them in a TreeMap. In your case, once you make the Dog class comparable (and the Dog objects contain a .age attribute) then you can store these Dog objects in a TreeSet (which is a sorted collection, sorted according to your compareTo() method in Dog).
You would instantiate the TreeSet as TreeSet<Dog> stack = new TreeSet<>();
I have two different types of objects, both of which have an integer which holds their priority. In another class I want to go through each object in an order that depends on those priorities, objects with higher priorities go before ones with lower priorities.
Now my issue is that the objects are of two different types. This makes it harder for me to sort them.
The class that cycles has two ArrayLists, one which holds objects of one type, the other holds objects of the other type.
Here is what I've thought of so far:
Create an ArrayList of Booleans and two ArrayLists of Integers.
Loop through the list of the first object type, adding a True Boolean to the Boolean list and the index in the object list to the Integer list, and the priority to the second Integer list.
Now loop through the list of the second type of object, adding a False boolean to the boolean list and the index in the second list to the Integer list, and the priority to the other integer list.
Now I would go through the ArrayList of priorities and sort so higher numbers come first. At the same time I would also sort the other two lists in the same way that I'm sorting the priority list.
In a scenario with few objects in each list, like four in each, this is what the Boolean list and the Integer list could look like:
Booleans: True, True, True, True, False, False, False, False
Index Integers: 0, 1, 2, 3, 0, 1, 2, 3
Priority Integers: 5, 7, 2, 3, 4, 6, 8, 1
After sorting by priority, it would look like this:
Booleans: False, True, False, True, False, True, True, False
Index Integers: 2, 1, 1, 0, 0, 3, 2, 3
Priority Integers: 8, 7, 6, 5, 4, 3, 2, 1
Now the class that cycles knows who goes first and what type of object it is.
This will work, but it is ugly and there has to be a quicker way to do this, or at the very least an easier way. Or perhaps do what I was planning but more efficiently. I am open to ideas of an entirely different algorithm or an adjustment to the algorithm I described.
Instead of having two lists, use one list that associates each key (priority) and value (index) in an object.
public class Set extends Comparable<Set>{
public Integer key;
public Integer value;
public Set(Integer key, Integer value){
this.key = key;
this.value = value;
}
public int compareTo(Set s){
return key.compareTo(s.key)
}
}
Since these Set objects are comparable to other Set objects, you can simply add them all to a single ArrayList and then call collections.sort() on that list.
Or you can take a look a priority queue.
http://docs.oracle.com/javase/7/docs/api/java/util/PriorityQueue.html
Although that may be over thinking things for your simple case.
If the two types of objects belong to classes that have a common super-class, you can store them in a single Collection of that super-class, and sort that Collection.
If not, you can still define an interface that both classes implement, such as Priorityable (since both have priority). Then you can store them in a Collection of that interface and sort the Collection by priority.
If it's essential that both types of objects remain in separate lists, sort each list separately based on the priority. Then define an Iterator that iterates over those lists in order. It is initialized by setting two indices (one for each list) to zero. The next() method would compare the priority of the next object in both lists to determine which should be returned next.
Collections.sort() will help you to compare values of different kinds of objects with each collection implementing java.util.Comparator would be a good possible option! But,do make sure that they can be compared using custom compare() implementations by all the collections(in your case ArrayList) as hinted by Elliott Frisch!
If you can change the definition of the two different objects that you have collections of, you can create an interface that defines the "priority" integer and have both object implement that interface. Once you have done that, you should probably just put them all into a single ordered collection that is ordered by the "priority" value.
In Java everything is an Object. So the commonality is Ojbect. The other commonality is the Integer priority, which is what needs to be sorted. So even if your items are Cats and Dogs with no Animal parent class, you can sort them simply demanding on whether you add elements often or read elements often:
if you add elements often then use a priority queue of arrays `{Integer, Object}
if you read elements often, then just use 2D array of Object[]=new Object[n][2]
In your priority queue of {Object, Object} where the first Object is Integer and the second is Cat or Dog, you sort on Integer.
Or in your n-by-2 array myObjects where myObjects[x][0] are Integers you sort your objects using any elementary algorithm as http://www.geekviewpoint.com/java/sorting/selectionsort
THEN is you only needed to sort once in a while, you partition the list into two sorted lists: one for Cats and one for Dogs. Otherwise, just keep the queue and walk it when needed. Also an alternative to using a queue is a BST as http://www.geekviewpoint.com/java/bst/add and walk in-order when you need a Cat or a Dog. If you like this answer and you want further help, let me know.
Let's say your two classes are Class1 and Class2. You should make them implement an interface like:
public interface Priorizable
{
int getPriority();
}
Then, create a Comparator for that interface:
public class PriorityComparator implement Comparator<Priorizable>
{
public int compare(final Priorizable p1, final Priorizable p2)
{
return Integer.compare(p1.getPriority(), p2.getPriority())
}
}
Put all your objects from Class1 and Class2 in a single list and sort:
Collections.sort(listOfPriorizable, new PriorityComparator());
The NavigableSet interface offers a number of useful methods that a normal Set does not (specifically I'm thinking about methods like headSet and tailSet for instance). However, being a Set, it does not support duplicate elements. Also, being a SortedSet, the ordering must be consistent with equals and hashCode to avoid violating the contract of the Set interface.
Is there any good alternative data structure for when there might be duplicate elements or multiple elements that are "equal" according to the natural ordering or Comparator but not "equal" according to the equals method? As a motivating example, consider the following code that shows why a NavigableSet is not appropriate:
public class Foo implements Comparable<Foo>{
double x;
double y;
#Override
public int compareTo(Foo o) {
return Double.compare(x, o.x); // only x matters for sort order
}
public static void main(String...args){
Foo a = new Foo();
a.x = 1;
a.y = 2;
Foo b = new Foo();
b.x = 1;
b.y = 42;
Foo c = new Foo();
c.x = 2;
c.y = 12.34;
NavigableSet<Foo> set = new TreeSet<Foo>();
set.add(a);
set.add(a);
set.add(b);
set.add(c);
System.out.println(set.size());
}
}
Notice that element a only gets added once (of course, since this is a Set). Also, notice that b does not get added, since there is already an element for which the comparison returns 0.
I felt like this was probably a fairly common thing, so I hoped to find an existing implementation rather than rolling my own. Is there a good, widely-used data structure for my purposes?
I'll add that while writing this question I did come across the Biscotti Project, but a) I'm not convinced it solves the comparison/equals issue and b) the FAQ explicitly says it's not really safe to use.
Let me reformulate your question to make sure I understand it well.
The need for headSet and tailSet implies the collection has to be sorted. Which is kind of in conflict with the need for allowing the duplicate members according to compareTo.
The conflict comes from the effective usage of such collection. Adding a member to sorted collection is done utilizing the compareTo method in O(log n) - kind of binary search and then add. The TreeSet is implemented using TreeMap which can't two same members according to compareTo.
What you are looking for won't be effective.
You may try to use a simple ArrayList and sort it by Collections.sort and then use sublist method. The problem with this is that it don't deal with duplicates at all.
You may also use the LinkedHashSet which deals with duplicates (according to equals() and it is immune to compareTo()), but it is not sorted. Of course, you may convert the LinkedHashSet instance to the SortedSet by passing its instance in constructor.
As a sample, I am developing a simple MySortedSet in java which implements SortedSet interface. It is backed up with a simple array which is E[] array.
I have several questions regarding that:
This is the class: (I am not writing entire code, instead of related parts)
public class MySortedSet<E> implements SortedSet<E>, Iterator<E> {
private E[] array;
private Comparator<? super E> _comparator;
private int size = 0;
private int capacity;
#SuppressWarnings("unchecked")
public MySortedSet() {
this.capacity = 10;
this.array = (E[]) new Object[this.capacity];
// this.array = Array.newInstance(Class<E> var,int size);
// We have to get Class<E> from outside caller.
}
}
Question 3: There is a explanation for Constructor since this is a sorted set so it is assumed the elements are sorted:
If this constructor is used to create the sorted set, it is assumed
that the elements are ordered using their natural ordering (i.e., E
implements Comparable).
It gets two different constructor. One is parameterless and the other one is accepting Comparator<? super E>.
public MySortedSet() {
this.capacity = 10;
this.array = (E[]) new Object[this.capacity];
// this.array = Array.newInstance(Class<E> var,int size);
// We have to get Class<E> from outside caller.
}
public MySortedSet(Comparator<? super E> comparator) {
this._comparator = comparator;
}
If comparator is not passed in, natural ordering should be used but I am not really sure how to accomplish it as I need to get Comparator in some way to access compare method. Do you guys please recommend me a way to call it so I can call it while comparing in sort method to sort each element.
For whom they like to see whole code, please refer to this address: http://codepaste.net/4ucvsw it is not perfect but I am working on it.
Question 4: The code guide says :
Because the fastest way to search for a particular item is to use a
binary search, you must ensure that the items in the collection are in
sorted order at all times. This won't be as hard to achieve as it may
seem. When you insert a new item, you can assume the array you are
inserting it into is already sorted. So all you need to do is find the
position in the array where the new item belongs, shift everything
greater than the new item one slot to the right, and insert the new
item. This is called insertion sort.
Here is the sort method logic. I am needed to make binary search to find where a new item belongs to so I can insert the new item in that place and move the other one slot to the right.
But I am not really sure how binary search will work for me here since I am not really sure what I need to find. I am given the item to add not the item to find. Instead what I think is to compare each element with the one I need to add and when I find the last smaller and first greater item, then I will get the first greater item's index, move them to the right and add new item at the index.
Question 3:
The fact is that every collection works with a predefined comparator, which is implicitly defined on the E, so that every class that will be used to concretize the type parameter E should implement Comparable<E>. The compare method you are looking for natural ordering is the method
int compareTo(E other)
that must be implemented by the classes that you are going to use with your data structure. Since your work is not related to defining classes to be used with your collection but just the collection itself what you are going to do it to have
public class MySortedSet<E> ... {
private Comparator<? super E> _comparator;
public int innerCompare(E e1, E e2)
{
if (_comparator != null)
return _comparator.compare(e1,e2);
else
return e1.compareTo(e2);
}
...
So that you'll use a custom comparator when provided, the natural one otherwise.
Both Comparable and Comparator work by following the same principle but the first one, as the name states, is attached to a data class, so that it is its natural comparator. The latter, instead, is used because it allows you to define a custom way to sort elements which would be sorted in a different way according to natural ordering.
Question 4:
What it means is that, under the assumption of having a sorted array, you just must keep this constraint valid after every insertion and you will be allowed to do binary search when looking for items.
You must focus just on placing the elements at correct index (the item you have to add). The part of the statement related to finding elements must be interpreted in the following way:
if you take care of keeping your array sorted, that can be done by ensuring that every element you add is placed in right position (eg with insertion sort), then you can apply binary search on the array when looking if an element is contained in the set.
This is true because, if the array is sorted, you can be sure that looking at the middle element of a section of the array will always point you to the right direction to see if another element is indeed contained in the list.
EG:
1, 2, 6, 11, 21, 30, 45
You need to check for 2, you can take element at index size()/2 = 3, which is 11. Since your already know that the array is sorted and 2 < 11 you can just do the same thing recursively on the left half and so on.
Answer 3:
"Natural ordering" means that the elements must implement Comparable so that they can be compared without the use of a Comparator. The tricky part about giving the caller a choice between Comparable elements and a Comparator is that you can't do compile time checking to make sure they fulfilled at least one of these requirements.
Java's TreeSet similarly exposes a constructor that takes a Comparator and others that don't. TreeSet's contract is essentially to throw a ClassCastException if you try to insert an element that isn't a Comparable if you didn't provide the TreeSet with a Comparator when you created it. Whether you want to use this strategy or another one is up to you.
Answer 4:
Based on the quote's strategy, you should be able to use Arrays.binarySearch(Object[], Object) for this exact purpose. From that method's documentation:
Returns: index of the search key, if it is contained in the array;
otherwise, (-(insertion point) - 1). The insertion point is defined as
the point at which the key would be inserted into the array: the index
of the first element greater than the key, or a.length if all elements
in the array are less than the specified key. Note that this
guarantees that the return value will be >= 0 if and only if the key
is found.
I want to push some int to a priorityqueue but i can't! i used the queue.add() code but this code will return the sorted queue,please help,thank you!
A push/pop operation is clearly defined for a stack abstract data type; I'm not sure if it makes sense for a queue (or even a priority queue).
PriorityQueueimplementsQueue, which only specifies add/remove. On the other hand, a Deque has addFirst/Last, removeFirst/Last, etc. Perhaps one of these is what you're looking for.
An example
Here's an example of using a PriorityQueue of String, using a custom Comparator that compares lengths.
Queue<String> queue = new PriorityQueue<String>(
100, new Comparator<String>() {
#Override public int compare(String s1, String s2) {
return Integer.valueOf(s1.length()).compareTo(s2.length());
}
}
);
queue.add("Sally");
queue.add("Amy");
queue.add("Alice");
System.out.println(queue);
// "[Amy, Sally, Alice]"
System.out.println(queue.remove());
// "Amy"
System.out.println(queue.remove());
// "Alice"
queue.add("Tina");
System.out.println(queue.remove());
// "Tina"
As expected, the PriorityQueue will give the shortest String in the queue upon remove. Also as specified, ties are broken arbitrarily.
Related questions
On PriorityQueue
Java: How do I use a PriorityQueue?
In Java what should I use for a PriorityQueue that returns the greatest element first?
On Comparator and Comparable
When to use Comparable vs Comparator
Java: What is the difference between implementing Comparable and Comparator?
difference between compare() and compareTo()
Comparable and Comparator contract with regards to null
Why does the Java Collections Framework offer two different ways to sort?
The whole point of a priority queue is that it returns the smallest entry (or rather, the first element that'd appear in a sorted list) first. If that's not what you want, you probably don't want a straight PriorityQueue.
What you could do is create a class that has a PriorityQueue for the usual stuff, and a stack for "emergencies". Have a push(T) method that adds stuff to the stack, and an add(T) that adds to the queue. Whatever method gets the next element should remove it from the stack if there's anything there, else it gets the queue's next element.
I want to push some int to a
priorityqueue
'Push' is a stack operation, not a queue operation.
but i can't! i used the
queue.add() code but this code will
return the sorted queue
No it won't. A PriorityQueue is only sorted for the purposes of removing the head of the queue.
Your question doesn't make much sense. If you want to push, use a stack. If you don't want what a PriorityQueue does, don't use it.
What exactly is your actual problem?