|
Quick Lists
|
|
Bug ID:
|
6356745
|
|
Votes
|
0
|
|
Synopsis
|
(coll) Add PriorityQueue(Collection, Comparator)
|
|
Category
|
java:classes_util
|
|
Reported Against
|
|
|
Release Fixed
|
|
|
State
|
5-Cause Known,
request for enhancement
|
|
Priority:
|
4-Low
|
|
Related Bugs
|
|
|
Submit Date
|
30-NOV-2005
|
|
Description
|
A DESCRIPTION OF THE REQUEST :
PriorityQueue does not have a constructor that accept a Collection and a Comparator.
JUSTIFICATION :
Most users will users will the next lines
Queue q = new PriorityQueue(comparate);
q.addAll(collection);
The running time for these lines is O(n log n), which defies a motivation to use such a priority queue.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
add the follwing method to the API.
public PriorityQueue( Collection<? extends E> c, Comparator<? super E> comparator);
to achieve an optimal O(n) running time
ACTUAL -
Suboptimal running time
---------- BEGIN SOURCE ----------
Queue q = new PriorityQueue(comparate);
q.addAll(collection);
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
PriorityQueue is not final, but it is not designed (nor documented) for inheritance.
Therefore the only bulletproof work around I found is to create an almost identical class with the same code and an additional constructor.
public PriorityQueueOptimized(Collection<? extends E> collection, Comparator<? super E> comparator) {
this.comparator = comparator;
initializeArray(collection);
fillFromUnsorted(collection);
}
Posted Date : 2005-11-30 00:56:01.0
|
|
Work Around
|
N/A
|
|
Evaluation
|
The suggested addition is consistent with existing APIs
in the collection classes.
Posted Date : 2005-11-30 05:58:50.0
An SDN member quite reasonably suggests,
"Why not just make a fast path for the addAll method and avoid the API change?
The TreeMap putAll method works that way."
Posted Date : 2006-03-03 20:53:47.0
There's something being missed here.
The only way initializing a PriorityQueue from another collection
could be O(N) is if the elements in the other collection are
already sorted into the desired order.
Any method or constructor taking an arbitrary collection and comparator
must be O(N*LOG(N)) to maintain the heap invariant.
Posted Date : 2006-03-05 17:41:58.0
|
|
Comments
|
Submitted On 02-MAR-2006
Jason-Mehrens
Why not just make a fast path for the addAll method and avoid the API change? The TreeMap putAll method works that way.
Submitted On 01-FEB-2007
Jason-Mehrens
Another issue with the current copy constructor is it allows null to be injected in to the PriorityQueue. A rare case but, it seems that the safest way to add items is O(N*LOG(N)).
import java.util.*;
public class QueueTest {
public static void main(String[] args) {
test(fill(new TreeSet<Comparable>(Nulls.HIGH)));
test(fill(new TreeSet<Comparable>(Nulls.LOW)));
test(fill(new ArrayList<Comparable>()));
}
private static void test(Collection<Comparable> c) {
try {
PriorityQueue pq = new PriorityQueue(c);
final Object[] a = pq.toArray();
if(Arrays.asList(a).contains(null))
if(!pq.contains(null))
System.out.println("Fail. "+ c.getClass().getName());
else
System.out.println("Pass.");
else
assert false;
}
catch(final NullPointerException NPE) {
System.out.println("Pass. PQ threw a "+ NPE.getClass().getName());
//NPE.printStackTrace(System.out);
}
}
private static Collection<Comparable> fill(Collection<Comparable> c) {
c.add(1);
c.add(null);
c.add(2);
return c;
}
private static class Nulls implements Comparator<Comparable> {
private static final Nulls HIGH = new Nulls(1);
private static final Nulls LOW = new Nulls(-1);
private final int modifier;
private Nulls(final int modifier) { this.modifier = modifier; }
public int compare(Comparable o1, Comparable o2) {
if(o1 != null && o2 != null)
return o1.compareTo(o2);
if(o1 == null)
return -1 * modifier;
return 1 * modifier;
}
}
}
/*
Fail. java.util.TreeSet
Fail. java.util.TreeSet
Pass. PQ threw a java.lang.NullPointerException
*/
PLEASE NOTE: JDK6 is formerly known as Project Mustang
|
|
|
 |