19

Which implementation is less "heavy": PriorityQueue or a sorted LinkedList (using a Comparator)?

I want to have all the items sorted. The insertion will be very frequent and ocasionally I will have to run all the list to make some operations.

1
  • 13
    msr - you should accept good answers to your questions, or people will stop answering you and your teeth will fall out. Commented Jul 27, 2010 at 15:56

11 Answers 11

33

A LinkedList is the worst choice. Either use an ArrayList (or, more generally, a RandomAccess implementor), or PriorityQueue. If you do use a list, sort it only before iterating over its contents, not after every insert.

One thing to note is that the PriorityQueue iterator does not provide the elements in order; you'll actually have to remove the elements (empty the queue) to iterate over its elements in order.

Sign up to request clarification or add additional context in comments.

3 Comments

You don't have to empty the queue to iterate over the elements in order. As per java documentation : "If you need ordered traversal, consider using Arrays.sort(pq.toArray())". Link: docs.oracle.com/javase/8/docs/api/java/util/PriorityQueue.html
@SobiborTreblinka Then you aren't iterating over the elements of the queue, but the elements of a new List. Since the user was specifically asking whether to use a List or a PriorityQueue, it wouldn't make sense to use a queue with its extra overhead if you end up using a list every time anyway.
Erickson, please see my answer bellow, I believe you are wrong and it's better to use LinkedList.
5

You should implement both and then do performance testing on actual data to see which works best in your specific circumstances.

5 Comments

Is there ever a circumstance where LinkedList would actually be faster for maintaining sorted entries with frequent inserts?
Yes. If the inserts happen very often, and the lookups don't, it might be best to just appened and sort on the lookup. You can cache whether it's been sorted or not. It depends on how often each occurs. That's where the testing comes in. This really should be a test question in a sophomore Data Structures class.
I meant if the list needed to be constantly sorted and not only sorted on demand. No need to be condescending.
I'd go with @Jeff's TreeSet. No need to implement and test. In a Linked List, both the insert and lookup will be O(n) assuming the list is always sorted. That's because unlike Arrays or ArrayLists, LinkedList will have to iterate from beginning to nth index to get the nth element, so you can't efficiently do Binary Search. The inserts are O(n) as well because it will first have to search the location to insert (assuming list is sorted) even though the insert operation itself will be O(1).
This answers all "X vs. Y" Stackoverflow questions, and therefore answers none.
3

I have made a small benchmark on this issue. If you want your list to be sorted after the end of all insertions then there is almost no difference between PriorityQueue and LinkedList(LinkedList is a bit better, from 5 to 10 percents quicker on my machine), however if you use ArrayList you will get almost 2 times quicker sorting than in PriorityQueue.

In my benchmark for lists I measured time from the beginning of filling it with values till the end of sorting. For PriorityQueue - from the beginning of filling till the end of polling all elements(because elements get ordered in PriorityQueue while removing them as mentioned in erickson answer)

Comments

3

adding objects to the priority queue will be O log(n) and the same for each pol. If you are doing inserts frequently on very large queues then this could impact performance. Inserting into the top of an ArrayList is constant so on the whole all those inserts will go faster on the ArrayList than on the priority queue.

If you need to grab ALL the elements in sorted order the Collections.sort will work in about O n log (n) time total. Where as each pol from the priority queue will be O log(n) time, so if you grab all n things from the queue that will again be O n log (n).

The use case where priority queue wins is if you are trying to find what the biggest value in the queue is at any given time. To do that with the ArrayList you have to sort the whole list each time you want to know the biggest. But with the priority queue it always knows what the biggest value is.

1 Comment

Does the java documentation mandate the algorithms that would give the performance you suggest?
2

If you use a LinkedList, you would need to resort the items each time you added one and since inserts are frequent, I wouldn't use a LinkedList. So in this case, I would use a PriorityQueue's If you will only be adding unique elements to the list, I recommend using a SortedSet (one implementation is the TreeSet).

4 Comments

An insert on PriorityQuery is documented as O(ln n). (Insertion into a LinkedList is O(n))
java.util.LinkedList is optimized for adding elements to the end of the list, making it an O(1) operation. However, sorting a LinkedList has horrible performance.
@erickson: Even for first and last inserts there is a better alternative in Java 6: java.util.ArrayDeque.
Be careful with SortedSet! It is the set's Ordering that determines whether or not a value is already in the set, not equals(). For example, if you have a SortedSet of Vectors ordered on the size of the vector, then the set will only hold one vector of length 4. Only use SortedSet if you are sure that different values will never be considered equal by the set's Ordering#compare.
2

There is a fundamental difference between the two data structures and they are not as easily interchangeable as you might think.

According to the PriorityQueue documentation:

The Iterator provided in method iterator() is not guaranteed to traverse the elements of the priority queue in any particular order.

Use an ArrayList and call Collections.sort() on it only before iterating the list.

Comments

1

The issue with PriorityQueue is that you have to empty the queue to get the elements in order. If that is what you want then it is a fine choice. Otherwise you could use an ArrayList that you sort only when you need the sorted result or, if the items are distinct (relative to the comparator), a TreeSet. Both TreeSet and ArrayList are not very 'heavy' in terms of space; which is faster depends on the use case.

Comments

0

Do you need it sorted at all times? If that's the case, you might want to go with something like a tree-set (or other SortedSet with a fast lookup).

If you only need it sorted occasionally, go with a linked list and sort it when you need access. Let it be unsorted when you don't need access.

Comments

0

java.util.PriorityQueue is

"An unbounded priority queue based on a priority heap"

. The heap data structure make much more sense than a linked list

Comments

0

I can see two options, which one is better depends on whether you need to be able to have duplicate items.

If you don't need to maintain duplicate items in your list, I would use a SortedSet (probably a TreeSet).

If you need maintain duplicate items, I would go with an LinkedList and insert new items into the list in the correct order.

The PriorityQueue doesn't really fit unless you want to remove the items whenever you do operations.

Going along with the others, make sure you use profiling to make sure you're picking out the correct solution for your particular problem.

Comments

-1

IMHO: we don't need PriorityQueue if if have LinkedList. I can sort queue with LinkedList faster than with PriorityQueue. e.g.

Queue list = new PriorityQueue();
list.add("1");
list.add("3");
list.add("2");
while(list.size() > 0) {
    String s = list.poll().toString();
    System.out.println(s);
}

I believe this code works too long, cause each time I add element it will sort elements. but if I will use next code:

Queue list = new LinkedList();
list.add("1");
list.add("3");
list.add("2");
List lst = (List)list;
Collections.sort(lst);
while(list.size() > 0) {
    String s = list.poll().toString();
    System.out.println(s);
}

I think this code will sort only once and it will be faster that using PriorityQueue. So, I can once sort my LinkedList once, before using it, in any case and it will work faster. And even if it sort the same time I don't really need PriorityQueue, we really don't need this class.

2 Comments

Are you trying to suggest that PriorityQueue is never useful?
No, I thought about it and I changed my mind, I think it useful when we need sorted Queue, it has interface for it. But questions was what: "Which implementation is less heavy". So, IMHO LinkedList will be faster and less heavy, it just little bit complicated, cause you need to use it as List to Sort, so you need to write more code, but it will work faster. So the right answer on question will be that LinkedList is less heavy.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.