To implement a Queue, why do we use?
Queue<Integer> q = new LinkedList<Integer>();
I mean a Superclass reference, why don't we use a LinkedList reference?
To implement a Queue, why do we use?
Queue<Integer> q = new LinkedList<Integer>();
I mean a Superclass reference, why don't we use a LinkedList reference?
We have a design principle called Code to interfaces never with concrete implementations
Here Queue is an Interface which can hold implementation class
Advantages over above principle
1.Switching between multiple implementations become easy in future
So it is always recommonded to code to interface instead of concrete implementations
2.If we won't use above principle we loose key Object oriented concept polymorphism.
You should always try to declare your variables with the least unnecessary restriction; often that means to an interface like Queue or Collection. This allows you to more easily change your implementation. I will use two classes from the collections framework as my example but the principle is general.
Imagine the following objective:
I need 2 collections that can have objects added to it. And I also need to be able to find which objects are in both collections. So in other words I need the following methods
Collection#add
Collection#retainAll
These are both within Collection so any collection will do. Collection is an interface so I need to choose a concrete implementation. I choose ArrayList, on a whim. My code is the following:
public static void main(String[] args){
Collection<Integer> a=new ArrayList<>();
Collection<Integer> b=new ArrayList<>();
initialise(a);
initialise(b);
testRetain(a,b);
}
public static void initialise(Collection<Integer> collection){
Random rnd=new Random();
for(int i=0;i<1000;i++){
collection.add(rnd.nextInt());
}
}
public static void testRetain(Collection<Integer> collection1, Collection<Integer> collection2){
collection1.removeAll(collection2);
}
This code works fine and does exactly what I asked it to do. However; in profiling I find that it is a bottleneck. So I test out different implentations of the Collection class and profile the results.
As you can see, for the retainAll operation the HashSet turned out to be much better. So I can change my implementation by changing just new ArrayList<>();
to new HashSet<>();
in one place. No need to change every other method I've used to HashSet
as well because they don't care, as long as they get some sort of Collection
they are happy
public static void main(String[] args){
Collection<Integer> a=new HashSet<>();
Collection<Integer> b=new HashSet<>();
initialise(a); //<--no need to alter this method
initialise(b);
testRetain(a,b); //<--no need to alter this method
}
Well that was easy. Now imagine a much larger application with dozens of methods; all of which could be hardcoded to use ArrayList
even though they didn't need to, all of which you would now need to manually alter.
To implement a Queue,why do we use?
No one can really assert that this is the patter that everyone must follow. You can very well use
LinkedListq=new LinkedList();
Reason above patter is used frequently because it offers the power of polymorphism. To explain it in short you now need a LinkedList
but later you may need PriorityQueue
. To use same reference for multiple concrete classes we use above pattern.