Consider the following declaration of the priority class class PriorityQueue<E extends Comparable<E>> extends Queue<E> { in contrast to the one provided in the Java packages, which has a comparator as an attribute to compare. This instead forces the object for which the priority queue is maintained to have its comparable implementation. Are there any pros and cons of this approach?
My Thoughts:
One thing I can think of is that this will force the priority queue to use the object comparators and won't provide the ability to implement its custom comparator as the user of the class may want to build the queue based on some different comparator.
Consider the following declaration of the priority class class PriorityQueue<E extends Comparable> extends Queue {}
What if you want to put an object in the queue, and this object does not implement the Comparable interface.
There is no need to restrict the placed object must implement the Comparable interface, which is more flexible.
For the same object, the logic of comparison may be inconsistent in different scenarios, so a comparator needs to be passed in from the outside, and the object itself does not need to implement a comparator.
(Above are my personal thoughts)
Related
I'm not sure what is the proper way to override all methods in Collection<E> interface.
I was asked to create a Class HotDog implements Collection<E>, thus i must override all methods it contains and I'm not sure how to do this since normally I believe the best solution would be to inherit from a class that allready implements Collection interface.
The requirements would be to have the functionality of a HotDog Object for the purposes of calculating the full price of the HotDog depending on the amount of ingredients the hotdog has, I believe the Collection functionality is for the ingredients in the hotdog.
There are three ways to create a new collection:
From scratch. You implement all methods of the Collection interface.
Extending an existing class, like you already mentioned. Java offers abstract classes for this purpose: java.util.AbstractCollection and various implementations for specific kinds of collection. These abstract classes allow you to focus on how the collections stores its elements instead of having to write all methods yourself.
Composition. Your class is basically a wrapper for an existing collection class and redirects all its method calls (except for a few whose behavior you want to adapt) directly to the wrapped collection's methods.
Which method is best depends on your particular requirements.
This was one quite a unique question I came across (Maybe someone must have). Someone asked me that can we implement both comparable and comparator interface in a single class? I had slight hint that it might be possible. Since I had never tried such a thing before... I examined it myself.. and hence posting this question so that others my find it quickly over here.
Technically you can do this, but this will be bad practice. When class implements Comparable that means that class has natural order. For example, value classes, such as Integer implement Comparable, so you can just pass a list of them into Collections.sort and get the expected result.
On the other hand, Comparator is basically designed to be used as anonymous classes when you need to create some custom ordering for other classes. Or to provide ordering for the class that doesn't have natural ordering.
There can be situation, when class should have additional orderings in addition to it's natural ordering. The best way to handle such situation is to create static constant comparators in such class. For example, if you have class Person with name and age, you can have natural order by name and add additional comparator that will order Persons by age.
class Person implements Comparable<Person> {
public static final Comparator<Person> BY_AGE_COMPARATOR = new Comparator<Person>() {
#Override
public int compare(Person o1, Person o2) {
return o1.age < o2.age ? -1 : (o1.age == o2.age ? 0 : 1);
}
};
private int age;
private String name;
#Override
public int compareTo(Person o) {
return name.compareTo(o.name);
}
}
This approach is better because you don't need instance of the class to access it's comparator. Also you can add as many additional comparators to the class as you want.
To summarize, you when class implements Comparator it often means that order some entities is the main purpose of such class. Implementing Comparable means that instances of this class could be sorted using some natural ordering. Having class both implement Comparable and Comparator means that you have natural order for orderings. This doesn't make sense.
Pros
If most of the time we have a specific sorting method to be used, Comparable interface's compareTo() method can be used. For example, Employee object most of the times needs to be sorted using the name attribute you will use a compareTo() method of Comparable interface and sort it using employee name. User of the employee object can directly use Collections.sort(empList).
In case when we have a requirement for a specific sorting order, the comparator implementation can be used. So in employee case if we have a requirement to sort by address, we can have an implementation for address and use it as a parameter to Collections.sort(empList, new Employee());
The employee object here would implement compare(Object emp,Object emp1).
Cons
Comparator Implementation should implement the comparison between two objects. Hence we would have to pass the employee object as a comparator which is not very intutive.
Design-wise ideally the comparator method does not belong to employee class as it is not using any attribute of employee object (this) which is calling it.
Yes we can extend any pojo class to implement both comparable and comparator interface and implement the methods defined by them.
I implemented it in sample Student POJO class.
When called Collections.sort(studentList) ... compareTo() is used.
When called Collections.sort(studentList, new Student()) ... compare() is used.
Advantages:
1) I have single class implementation for both comparable and comparator interfaces.
Disadvantages:
1) I can define only one comparable and only one comparator inside one class.
2) Now to define any new comparator I have to move out to other class or define it on the fly (annonymous class).
3) But the motive of comparator is lost.Comparator provides an external implementation for comparison of class objects outside the class. Defining it inside might include confusion as to what is called and when?
People can add more points if I have missed out on any...
public class testCast {
public interface dataQueue extends Queue<Object>{};
public static void main (String test[]){
dataQueue queue = (dataQueue) new java.util.PriorityQueue<Object>();
queue.add("Test");
System.out.println(queue.peek());
}
}
I am wondering why this would cause a casting error....
it would work if I do
Queue queue = (Queue) new java.util.PriorityQueue<Object>();
Does anyone know why??
Thanks in advance
Put simply, because a PriorityQueue is a Queue, but not a DataQueue. The actual class definition matters in Java: just because two interfaces are identical doesn't mean you can cast any implementation of one to the other.
DataQueue is an interface that extends the Queue interface.
PriorityQueue is a class that implements the Queue interface.
It does not implement the DataQueue interface.
Therefore, a PriorityQueue cannot be cast to DataQueue.
The hierarchy might make it clearer: just because they have a common ancestor doesn't mean you can cast one to the other.
Queue
________|________
| |
DataQueue PriorityQueue
To be even more pedantic about it, let's ramp up the clarity, since the relationship between Queue and DataQueue is different from the relationship between Queue and PriorityQueue. The following MSPaint diagram uses solid lines for inheritance, and dashed lines for interface-implementation.
So, you can't get from a PriorityQueue directly to a DataQueue. If you did really want to be able to make a PriorityQueue and call it a DataQueue for some reason, this is what you could do: extend PriorityQueue with a new class, and implement your DataQueue interface.
public class MyQueue extends PriorityQueue<Object> implements DataQueue {
// Anything you want goes here, or just leave it empty if you only want the default constructor.
}
Then you can write DataQueue q = new MyQueue(); to your heart's content.
Finally, note that this wouldn't work if you tried to inherit from two different classes. Java does not support multiple inheritance. This hierarchy is only possible because DataQueue is an interface, rather than a class.
I was reading http://www.docjar.com/html/api/java/util/LinkedList.java.html
When you declare a queue in Java
Queue<Integer> queue = new LinkedList<Integer>();
What happens behind the scene ? because I see queue is an interface with just method signatures, and LinkedList doesn't directly implement it, so how does it override those methods (add(), peek(), poll(), offer(), and remove() ) and do the polymorphism like that ? I mean you can only access some certain methods but not all of them from LinkedList for example public void add(int index, E element) is no longer available as it makes the apparent type to Queue. Also didn't we need to cast it ?
From the source code of the JDK:
public class LinkedList<E>
extends AbstractSequentialList<E>
implements List<E>, Deque<E>, Cloneable, java.io.Serializable
{
So LinkedList<E> doesn't directly implement Queue<E>, but it does implement Deque<E>, which extends Queue<E>:
public interface Deque<E> extends Queue<E> {
Threfore, LinkedList<E> inherits the abstract methods of Queue<E>.
The overriding methods are defined directly in LinkedList<E> - as usual.
because I see queue is an interface with just method signatures, and LinkedList doesn't directly implement it
LinkedList does implement a Queue: http://docs.oracle.com/javase/6/docs/api/java/util/LinkedList.html
Refer this
http://docs.oracle.com/javase/7/docs/api/java/util/LinkedList.html
LinkedList does implement Queue. When an object is declared using an interface, the compiler treats it solely as an object of that type. however, since you cannot instantiate an interface, you need to instantiate it as a class that implements that interface. In this case, you will not be able to access some of LinkedList's methods, (push(), pop(), for example), because the compiler identifies queue as a Queue<Integer>. However, since it was instantiated as a LinkedList<Integer>, and can be casted easily to a LinkedList.
Why do many Collection classes in Java extend the Abstract class and also implement the interface (which is also implemented by the given abstract class)?
For example, class HashSet extends AbstractSet and also implements Set, but AbstractSet already implements Set.
It's a way to remember that this class really implements that interface.
It won't have any bad effect and it can help to understand the code without going through the complete hierarchy of the given class.
From the perspective of the type system the classes wouldn't be any different if they didn't implement the interface again, since the abstract base classes already implement them.
That much is true.
The reason they do implement it anyways is (probably) mostly documentation: a HashSet is-a Set. And that is made explicit by adding implements Set to the end, although it's not strictly necessary.
Note that the difference is actually observable using reflection, but I'd be hard-pressed to produce some code that would break if HashSet didn't implement Set directly.
This may not matter much in practice, but I wanted to clarify that explicitly implementing an interface is not exactly the same as implementing it by inheritance. The difference is present in compiled class files and visible via reflection. E.g.,
for (Class<?> c : ArrayList.class.getInterfaces())
System.out.println(c);
The output shows only the interfaces explicitly implemented by ArrayList, in the order they were written in the source, which [on my Java version] is:
interface java.util.List
interface java.util.RandomAccess
interface java.lang.Cloneable
interface java.io.Serializable
The output does not include interfaces implemented by superclasses, or interfaces that are superinterfaces of those which are included. In particular, Iterable and Collection are missing from the above, even though ArrayList implements them implicitly. To find them you have to recursively iterate the class hierarchy.
It would be unfortunate if some code out there uses reflection and depends on interfaces being explicitly implemented, but it is possible, so the maintainers of the collections library may be reluctant to change it now, even if they wanted to. (There is an observation termed Hyrum's Law: "With a sufficient number of users of an API, it does not matter what you promise in the contract; all observable behaviors of your system will be depended on by somebody".)
Fortunately this difference does not affect the type system. The expressions new ArrayList<>() instanceof Iterable and Iterable.class.isAssignableFrom(ArrayList.class) still evaluate to true.
Unlike Colin Hebert, I don't buy that people who were writing that cared about readability. (Everyone who thinks standard Java libraries were written by impeccable gods, should take look it their sources. First time I did this I was horrified by code formatting and numerous copy-pasted blocks.)
My bet is it was late, they were tired and didn't care either way.
From the "Effective Java" by Joshua Bloch:
You can combine the advantages of interfaces and abstract classes by adding an abstract skeletal implementation class to go with an interface.
The interface defines the type, perhaps providing some default methods, while the skeletal class implements the remaining non-primitive interface methods atop the primitive interface methods. Extending a skeletal implementation takes most of the work out of implementing an interface. This is the Template Method pattern.
By convention, skeletal implementation classes are called AbstractInterface where Interface is the name of the interface they implement. For example:
AbstractCollection
AbstractSet
AbstractList
AbstractMap
I also believe it is for clarity. The Java Collections framework has quite a hierarchy of interfaces that defines the different types of collection. It starts with the Collection interface then extended by three main subinterfaces Set, List and Queue. There is also SortedSet extending Set and BlockingQueue extending Queue.
Now, concrete classes implementing them is more understandable if they explicitly state which interface in the heirarchy it is implementing even though it may look redundant at times. As you mentioned, a class like HashSet implements Set but a class like TreeSet though it also extends AbstractSet implements SortedSet instead which is more specific than just Set. HashSet may look redundant but TreeSet is not because it requires to implement SortedSet. Still, both classes are concrete implementations and would be more understandable if both follow certain convention in their declaration.
There are even classes that implement more than one collection type like LinkedList which implements both List and Queue. However, there is one class at least that is a bit 'unconventional', the PriorityQueue. It extends AbstractQueue but doesn't explicitly implement Queue. Don't ask me why. :)
(reference is from Java 5 API)
Too late for answer?
I am taking a guess to validate my answer. Assume following code
HashMap extends AbstractMap (does not implement Map)
AbstractMap implements Map
Now Imagine some random guy came, Changed implements Map to some java.util.Map1 with exactly same set of methods as Map
In this situation there won't be any compilation error and jdk gets compiled (off course test will fail and catch this).
Now any client using HashMap as Map m= new HashMap() will start failing. This is much downstream.
Since both AbstractMap, Map etc comes from same product, hence this argument appears childish (which in all probability is. or may be not.), but think of a project where base class comes from a different jar/third party library etc. Then third party/different team can change their base implementation.
By implementing the "interface" in the Child class, as well, developer's try to make the class self sufficient, API breakage proof.
In my view,when a class implements an interface it has to implement all methods present in it(as by default they are public and abstract methods in an interface).
If we don't want to implement all methods of interface,it must be an abstract class.
So here if some methods are already implemented in some abstract class implementing particular interface and we have to extend functionality for other methods that have been unimplemented,we will need to implement original interface in our class again to get those remaining set of methods.It help in maintaining the contractual rules laid down by an interface.
It will result in rework if were to implement only interface and again overriding all methods with method definitions in our class.
I suppose there might be a different way to handle members of the set, the interface, even when supplying the default operation implementation does not serve as a one-size-fits-all. A circular Queue vs. LIFO Queue might both implement the same interface, but their specific operations will be implemented differently, right?
If you only had an abstract class you couldn't make a class of your own which inherits from another class too.