I have been investigating the best way to move an ArrayList to a PriorityQueue, and I have found that the best way to do it is by using the method pq.addAll(dataArrayList). But the problem I have now, is how to pass this PriorityQueue, pq, already ordered to the same previous DataArrayList.
The only way I can think of doing it is a structure that runs through the queue, and if the queue is not empty, it extracts and adds in dataArrayList.
public void sort2(Comparator<Router> comp){
PriorityQueue<Router> pq = new PriorityQueue<Router>(comp);
pq.addAll(datos);
datos.clear();
while(!pq.isEmpty()) {
datos.add(pq.poll());
}
}
Router is an ArrayList of Strings(it is actually a class with ip address, city, identifier, but so that we understand each other better we treat it as a String), for example ["a","c","b"] and sort by LessOrder --> ["a","b","c"].
It works, but is it the best way to implement this? Thanks.
Related
I have implemented a graph.
I want to sort a given subset of vertices with respect to their degrees.
Therefore, I've written a custom comparator named DegreeComparator.
private class DegreeComparator implements Comparator<Integer>
{
#Override
public int compare(Integer arg0, Integer arg1)
{
if(adj[arg1].size() == adj[arg0].size()) return arg1 - arg0;
else return adj[arg1].size() - adj[arg0].size());
}
}
So, which one of the below is more efficient?
Using TreeSet
public Collection<Integer> sort(Collection<Integer> unsorted)
{
Set<Integer> sorted = new TreeSet<Integer>(new DegreeComparator());
sorted.addAll(unsorted);
return sorted;
}
Using ArrayList
Collections.sort(unsorted, new DegreeComparator());
Notice that the second approach is not a function, but a one-line code.
Intuitively, I'd rather choose the second one. But I'm not sure if it is more efficient.
Java API contains numerous Collection and Map implementations so it might be confusing to figure out which one to use. Here is a quick flowchart that might help with choosing from the most common implementations
A TreeSet is a Set. It removes duplicates (elements with the same degree). So both aren't equivalent.
Anyway, if what you want naturally is a sorted list, then sort the list. This will work whether the collection has duplicates or not, and even if it has the same complexity (O(n*log(n)) as populating a TreeSet, it is probably faster (because it just has to move elements in an array, instead of having to create lots of tree nodes).
If you only sort once, then the ArrayList is an obvious winner. The TreeSet is better if you add or remove items often as sorting a list again and again would be slow.
Note also that all tree structures need more memory and memory access indirection which makes them slower.
If case of medium sized lists, which change rather frequently by a single element, the fastest solution might be using ArrayList and inserting into the proper position (obviously assuming the arrays get sorted initially).
You'd need to determine the insert position via Arrays.binarySearch and insert or remove. Actually, I would't do it, unless the performance were really critical and a benchmark would show it helps. It gets slow when the list get really big and the gain is limited as Java uses TimSort, which is optimized for such a case.
As pointed in a comment, assuring that the Comparator returns different values is sometimes non-trivial. Fortunately, there's Guava's Ordering#arbitrary, which solves the problem if you don't need to be compatible with equals. In case you do, a similar method can be written (I'm sure I could find it somewhere if requested).
I have implemented a graph.
I want to sort a given subset of vertices with respect to their degrees.
Therefore, I've written a custom comparator named DegreeComparator.
private class DegreeComparator implements Comparator<Integer>
{
#Override
public int compare(Integer arg0, Integer arg1)
{
if(adj[arg1].size() == adj[arg0].size()) return arg1 - arg0;
else return adj[arg1].size() - adj[arg0].size());
}
}
So, which one of the below is more efficient?
Using TreeSet
public Collection<Integer> sort(Collection<Integer> unsorted)
{
Set<Integer> sorted = new TreeSet<Integer>(new DegreeComparator());
sorted.addAll(unsorted);
return sorted;
}
Using ArrayList
Collections.sort(unsorted, new DegreeComparator());
Notice that the second approach is not a function, but a one-line code.
Intuitively, I'd rather choose the second one. But I'm not sure if it is more efficient.
Java API contains numerous Collection and Map implementations so it might be confusing to figure out which one to use. Here is a quick flowchart that might help with choosing from the most common implementations
A TreeSet is a Set. It removes duplicates (elements with the same degree). So both aren't equivalent.
Anyway, if what you want naturally is a sorted list, then sort the list. This will work whether the collection has duplicates or not, and even if it has the same complexity (O(n*log(n)) as populating a TreeSet, it is probably faster (because it just has to move elements in an array, instead of having to create lots of tree nodes).
If you only sort once, then the ArrayList is an obvious winner. The TreeSet is better if you add or remove items often as sorting a list again and again would be slow.
Note also that all tree structures need more memory and memory access indirection which makes them slower.
If case of medium sized lists, which change rather frequently by a single element, the fastest solution might be using ArrayList and inserting into the proper position (obviously assuming the arrays get sorted initially).
You'd need to determine the insert position via Arrays.binarySearch and insert or remove. Actually, I would't do it, unless the performance were really critical and a benchmark would show it helps. It gets slow when the list get really big and the gain is limited as Java uses TimSort, which is optimized for such a case.
As pointed in a comment, assuring that the Comparator returns different values is sometimes non-trivial. Fortunately, there's Guava's Ordering#arbitrary, which solves the problem if you don't need to be compatible with equals. In case you do, a similar method can be written (I'm sure I could find it somewhere if requested).
So I have this simple code in java. It enqueue (adds) and element to the end of the queue (implemented by an ArrayList) without changing the original queue. The code:
public class MyQueue<T>{
private List<T> body;
// some constructors and helper functions.
//copy constructor
public Queue(List<T> list){
this.body = list;
}
//this is the function
public MyQueue<T> enqueue(T obj){
List<T> temp = new ArrayList<T>(body);
temp.add(obj);
return new Queue<T>(temp);
}
The whole Idea is to make enqueue faster and more efficient, and again, as you notice, without changing the value of the original queue.
UPDATE For the sake of completing the idea.
1- This is an assignment so university, the skeleton provided is not to be changed, the task is to make the function enqueue faster (i do realize i am copying twice and thats the slow part).
2- As for the helper functions, they are simple:
public T peek(){
if(body.isEmpty()){
thrown new NoSuchElementException();
}
return body.get(0);
}
public int size(){
return body.size();
}
Any ideas? thanks
A queue is a basic data structure and it's hard to make it better than the experts having worked on it. The simplest and fastest general purpose implementation is probably the ArrayDeque and there's hardly anything to improve.
What you're doing is strange at best:
Instead of appending an element, you copy the whole content. Why?
You insert the new element at the highest index, why? This way your poll (dequeue, remove, whatever) must remove the index at element 0, which is slow for ArrayList.
Actually, I have no idea how your poll may look like. In any case, your enqueue doesn't do what I'd expect from a method called like this.
Use a LinkedList instead of an ArrayList. You don't need indexed access in a queue, but you do need fast enqueue/dequeue. If you need indexed access. It isn't really a queue at all. And just use the add() method, don't create a whole new queue every time. Your enqueue() method should return 'this', or void. And don't allow the caller to supply the list: create your own.
I want to implement a FIFO queue with containing different data types in java. Also I need to know whether I can store an array as one of the types inside the queue. Simply what I need is to store Strings and String arrays in the queue.Any help??
thanx
Remember that arrays are java.lang.Objects in Java. So the following works fine:
Queue<Object> queue = new LinkedList<Object> ();
queue.add("string0");
queue.add(new String[] {"string1", "string2"});
Keep in mind though that iterating this collection will then likely require using instanceof. You may be better of making all entries string arrays, and just making the single strings arrays of size 1. That way your iteration logic becomes easier.
Queue<String[]> queue = new LinkedList<String[]> ();
queue.add(new String[] {"string0"});
queue.add(new String[] {"string1", "string2"});
for (String[] nextArray : queue) {
for (String nextString : nextArray) {
System.out.println("nextElement: " + nextString);
}
}
Having different types in your data structure will make more difficult and error prone to use it.
In this case is better to have some wrapper that will make all accesses to your work in the same way.
Try to understand better your domain to see you if you have a natural domain class to hold the value in the key. (What do you want to put in the Queue? a Message, a Request, what kind of Message or Request?, etc)
Otherwise create a immutable class to encapsulate the different type your Queue can accept, a different constructor for each type it should accept. If you start to have more behavior to each case Extract Hierarchy is your friend :) This way your domain class can evolve in a natural way.
As #Melv has pointed out, you can simply use a Queue of Objects.
But using Objects means giving up the type safety and being forced to use the instanceof operator. an alternative can be to use a Queue<String[]> instead. Whenever you need to insert a single String, you can just push a single element String array (i.e. Queue.offer(new String[]{element})).
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?