The order of the PriorityQueue is wrong - java

I meet a problem about order of PriorityQueue in Java 8, Intellij Idea, when I add the third number in the queue, the order is wrong, but only the third one have this problem, here is my code.
import java.util.*;
public class vector {
static Queue<Integer> q=new PriorityQueue<Integer>();
public static void addNum(int num) {
q.add(num);
}
public static void main(String args[]) {
addNum(-1);
addNum(-2);
addNum(-3);
addNum(-4);
addNum(-5);
}
}
I try to debug the code, after addNum(-3), the queue is -3,-1,-2, but after addNum(-4), the queue is -4, -3, -2, -1.

The contract for PriorityQueue does not guarantee iteration order, but rather it guarantees that each element removed from the priority queue will follow either the natural ordering of the queue's type, or the ordering of a custom comparator, should one be provided.
The Javadoc comments on what you are seeing:
Queues typically, but do not necessarily, order elements in a FIFO (first-in-first-out) manner. Among the exceptions are priority queues, which order elements according to a supplied comparator, or the elements' natural ordering, and LIFO queues (or stacks) which order the elements LIFO (last-in-first-out).
The contract which Java appears to enforce for priority queues is that the first element removed from the queue will follow the natural order of the object in the queue, or using a custom comparator, should one be provided.
If we add to your current script to remove the five elements added, we will see that the items returned will be ordered from least to greatest:
public static void main(String args[]) {
addNum(-1);
addNum(-2);
addNum(-3);
addNum(-4);
addNum(-5);
// now remove all elements
while (!q.isEmpty()) {
System.out.println(q.remove());
}
}
This prints:
-5
-4
-3
-2
-1
If you need a collection which maintains sorting order, then consider using something like TreeSet. Or, you could use a regular ArrayList, and then call Collections.sort() if you want to impose a certain order.

PriorityQueue's implementation is a priority heap implementation & not sorted list.
The Iterator provided in method iterator() is not guaranteed to traverse the elements of the priority queue in any specific order. If you need ordered traversal, use something like:
Arrays.sort(q.toArray());
for (Integer data :q) {
System.out.println(data);
}

As other answers implied, you should use queue.poll() if you want to retrieve the elements in the right order, as in:
List<E> entities = new ArrayList<>();
while(!queue.isEmpty()){
entities.add(queue.poll());
}
The order of entities in the entities list will be as expected.
Rationale: Java PriorityQueue only ensures the order of enqueuing of the entities, not the order of iteration in an underlying collection.
The entities are mapped onto an underlying collection "unsorted", meaning if you try to access the entities using a stream:
queue.stream().collect(Collectors.toList());
or an iterator:
Iterator<E> i = queue.iterator();
...
E e = i.next()
or any other method, such as queue.forEach(), or in fact observe your queue in a IDE debugger, there is no guarantee as to the order of the entries in the collections obtained using any of these methods.

This the most Common Question, Many Collection Frame Work like ArrayList, LinkedList, and furthermore but In PriorityQueue, when you are printing the elements it will be in the Sorted Order and that order is followed MIN_HEAP property or
Basically, we can say that the Priority Queue is implemented on Min Heap Property.
So First Understand the MinHeap then implement the code.

Related

How can Iterator can using in set(java)?

my question was why does iterator work on set?
Here is my example code,
public class Staticex {
public static void main(String[] args) {
HashSet set = new HashSet();
set.add(1);
set.add(2);
set.add(3);
set.add(4);
set.add(5);
Iterator iter = set.iterator();
while (iter.hasNext()) {
System.out.println(iter.next());
}
}
}
I understand, set is unordered, In contrast List
So, How can get the values ​​one by one through an iterator?
Is iterator changing set into like list which ordered data structure?
How can Iterator can using in set?
Like you are using it.
How can get the values ​​one by one through an iterator?
Your code is doing that.
Is iterator changing set into like list which ordered data structure?
No.
The thing that you are missing is what "unordered" means. It means that the order in which the (set's) elements are returned is not predictable1, and not specified in the javadocs. However each element will be returned once and (since the elements of a set are unique!) only once for the iteration.
1 - Actually, this is not strictly true. If you have enough information about the element class, the element values, how they were created and how / when they were added to the HashSet, AND you analyze the specific HashSet implementation ... it is possible that you CAN predict what the iteration order is going to be. For example if you create a HashSet<Integer> and add 1, 2, 3, 4, ... to it, you will see a clear (and repeatable) pattern when you iterate the elements. This is in part due to the way that Integer.hashCode() is specified.
Referring to the documentation, we see that:
Iterator<E> iterator()
Returns an iterator over the elements in this collection. There are no guarantees concerning the order in which the elements are returned (unless this collection is an instance of some class that provides a guarantee).
Since there are no guarantees concerning the order in which the elements are returned for iterator, it is not a problem for iterator to apply to Set, which is unordered.
Further, it is not changing the Set into a List
Set is unordered in a logical sense. When you have a bag of things, there isn't a sense of order when they are inside the bag. But when you take each thing out of the bag, one at a time, you end up with some order. And like the other answer has mentioned, you cannot rely on that order since it is purely accidental.
I understand, set is unordered, In contrast List
This is not necessarily true. SortedSet is a subinterface of Set. As the name implies, instances of this interface are ordered in some fashion. For example, TreeSets are ordered using their natural ordering, or by a Comparator provided at set creation time, depending on which constructor is used. Also, the main distinction between Set and List is that List allows for duplicate objects to be contained, whereas Set does not.
Now, if you are talking specifically about HashSet, then you are correct about being unordered.
I think your confusion is because you are asking yourself "why is the print out showing the numbers in numeric (insertion) order?" This is sort of a complicated answer for someone of your familiarization level, but the order in which they are printed out is because you are inserting integers and their hash code are basically their numeric values. And, although there is no guarantee as to the order in which the elements of the hash set are returned when iterating, the implementation of HashSet is backed by a hash table. In fact, if you change the insertion order of those same values, most likely the numbers will be printed out in the same numeric order. Now, remember that with all that, the order is not guaranteed. This may not be true, for instance, if you change the set elements to be String objects.

How the priority will be given in PriorityQueue when some random elements are added?

when I add some random numbers in a PriorityQueue, when I print the PriorityQueue the elements are printed in different order.
how it is happening?
example
PriorityQueue<Integer> s=new PriorityQueue<Integer>();
s.add(22);
s.add(212);
s.add(423);
s.add(323);
s.add(1);
System.out.print(s);
output:
[1, 22, 423, 323, 212]
It has no guaranteed order (https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/PriorityQueue.html):
The Iterator provided in method iterator() and the Spliterator provided in method spliterator() are 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()).
Normally you retrieve elements according to their natural order using the poll() method, for example:
while (!pq.isEmpty()) {
var element = pq.poll();
...
}
toString() returns a representation of the internal storage of the priority queue, not of the logical order of the elements. The same is true for toArray() and for iteration: none of these methods guarantee that the elements will be returned in their order of priority.
If you want to obtain the elements in the order of priority, you need to poll() them individually (and thus destroy the queue). PriorityQueue is thus not a suitable data structure if you want to list the elements in a particular order. A SortedSet would be more appropriate here. By contrast, queue data structures (of which PriorityQueue is a special case) are used for receiving and retrieving elements once, not for inspecting data at rest.

Not able to understand how PriorityQueue is changing the sort order?

import java.util.*;
class abc {
public static void main(String args[]){
PriorityQueue<Integer> pq = new PriorityQueue<Integer>();
pq.add(1);
pq.add(2);
pq.add(3);
pq.add(4);
pq.add(5);
pq.add(6);
System.out.println(pq);
pq.remove();
System.out.println(pq);
}
}
When I remove the element, order changes.
Output should be in ascending order according to lexicographical sorting. But I am getting output as:
Calling System.out.println(pq); is the same as calling System.out.println(pq.toString());
If you look at the documentation of the the toString() method, you'll see that it states:
Returns a string representation of this collection. The string
representation consists of a list of the collection's elements in the
order they are returned by its iterator, enclosed in square brackets
("[]"). Adjacent elements are separated by the characters ", " (comma
and space). Elements are converted to strings as by
String.valueOf(Object).
I highlighted the important part. So we need to have a look the the documentation of the iterator of the priority queue which states:
Returns an iterator over the elements in this queue. The iterator does
not return the elements in any particular order.
So the output of your code does not allow any conclusions of the order imposed by the priority queue.
In the main documentation of the PriorityQueue it says:
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()).
PriorityQueue implements a Heap data structure. This data structure has the property to keep your elements partially sorted. Heap is a binary tree (even if in practice it's implemented in an array) that maintain the following invariance: If the node P has a child C, the value of P is smaller/bigger than the value of C.
Therefore only the first element (the root) is guaranteed to be the minimum/maximum of the collections, while all the other values are only partially sorted.
Why do that? Well, if you have to keep a completed sorted collection, the insert/delete operations will take O(n), while with an heap data structure they both are O(log n). If you're only interested in the max/min of the collection, then PriorityQueue has a significant advantage over a completed sorted array.
From the documentation of AbstractCollection's toString() method (which is invoked when you pass your queue to the System.out.println() method):
The string representation consists of a list of the collection's
elements in the order they are returned by its iterator, [...]
From the documentation of PriorityQueue's iterator() method:
Returns an iterator over the elements in this queue. The iterator does
not return the elements in any particular order.
There's your answer right there.

TreeSet definition of an iterator is not consistent with the interface Iterator?

I am using some legacy code which uses TreeSet to perform the sort of a collection of objects. (alternatives to using TreeSet are a good reference, but I am not looking to change that in particular).
The class has two methods iterator()
iterator()
Returns an iterator over the elements in this set in ascending order.
and descendingIterator()
descendingIterator()
Returns an iterator over the elements in this set in descending order.
My concept of the Iterator interface implemented by a Collection or in own implementation, is that you can not assume any specific ordering.
In the implementation already provided it is assumed that the two calls give an iterator in correct ordering. The results are good for now, my fear is that it is a false assumption and since it violates the Iterator interface principles, it could change in the future.
I do not have experience with TreeSet and I do not see traversal methods to poll the elements in order. Is there a way to do this or just stick with the Iterator's and hope for the best?
EDIT
Example usage:
TreeSet<BeatDesc> beatsOrderedTS = new TreeSet<>(new Comparator<BeatDesc>() {
#Override
public int compare(BeatDesc lhs, BeatDesc rhs) {
return lhs.getTS() - rhs.getTS() < 0 ? -1 : 1;
}
});
BeatDesc latest = beatsOrderedTS.descendingIterator().next()
EDIT
{//block 1
Iterator<BeatDesc> itBeatDesc = beatsOrderedTS.descendingIterator();
}
{//block 2
for (BeatDesc beatDesc : itBeatDesc){
....
}
So by using this format you create a binding between block 1 and block 2
I don't know where you got the idea that "you can not assume any specific ordering" of the elements returned by an Iterator. The javadoc just says:
An iterator over a collection.
It doesn't say anything about ordering.
Now, the javadoc of the iterator() method of Collection says:
Returns an iterator over the elements in this collection. There are no guarantees concerning the order in which the elements are returned (unless this collection is an instance of some class that provides a guarantee).
For example, TreeSet, LinkedHashSet, EnumSet, and all List implementations do guarantee a defined order:
TreeSet - The elements are ordered using their natural ordering, or by a Comparator provided at set creation time, depending on which constructor is used.
LinkedHashSet - This linked list defines the iteration ordering, which is the order in which elements were inserted into the set (insertion-order).
EnumSet - The iterator returned by the iterator method traverses the elements in their natural order (the order in which the enum constants are declared).
List - An ordered collection (also known as a sequence). - iterator() returns an iterator over the elements in this list in proper sequence.
TreeSet is meant to maintain the order (either ascending or descending) of the elements as per either :
The Object that you are going to insert into the set implement's Comparable something like:
class MyObject implements Comparable<MyObject> {..
while constructing TreeSet where you pass your implementation of how you want to order elements within set by implementing Comparator interface something like:
class MyComparator implements Comparator<MyObject> {..
... new TreeSet<>(new MyComparator());
Hence it is guaranteed you would get the elements in order as per your implementation of those interfaces.

push in priorityqueue

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?

Categories