I am trying to teach my students the proper way to use Java generics. I am teaching a data structures course, so I want them working with arrays and their own linked lists, not with the Java Collections (for example no ArrayList). A typical issue is providing an array implementation for an ADT. Here is an example where I am trying to use a heap implemented as an array to provide a Priority Queue. I would like to support a priority queue of any kind of data objects so I use a generic I start with an interface:
public interface PriQue<E> {
void insert(int pri, E data);
E remove(); // return null when empty
boolean isEmpty();
}
Then I implemented it:
public class ArrayHeap<E> implements PriQue<E> {
//private class Entry<E> { hides E of ArrayHeap which means remove fails
private class Entry { // uses E of ArrayHeap
int pri;
E data;
. . .
} // end of Entry
Entry heap[];
int cnt;
public ArrayHeap(int size) {
// heap = new Entry[size]; can not create generic array error
// heap = (Entry[])new Object[size]; blows up on a cast error
heap = (Entry[])new Object[size];
cnt = 0;
}
. . .
public E remove() {
E tmp = (E)heap[--cnt].getData(); //bad don't want to cast
// trickle down code here
return tmp;
}
Since the interface is parameterized I use the same generic in the implementing class – I think this is ok.
I need to create an array of entries that will hold a priority and the corresponding data item. So I create a private class. Here my problem begins. If I leave the parameter out then since it is part of ArrayHeap it should pick up the E generic form there. This compiles but blows up when I try to create an array of Entry. Alternately I can have an explicit generic parameter to Entry. If I pick E it will “hide” E from ArrayHeap and when I try to remove an E from the array it does not realize it is the same E as the ArrayHeap E. If I name it something else, say V, then it cannot assign an E to a V and I cannot store any data. I think this is a fairly common situation in implementing a data structure.
I’ve tried reading http://www.angelikalanger.com/GenericsFAQ/FAQSections/ParameterizedTypes.html#FAQ104
But it does not cover a nested class (and its mostly about what does not work)
I’ve tried reading the code for the Java collections map implementation and I don’t see what is different.
V. Then, when you declare the instance if the inner class you useE-Entry<E> heap[];. This is when you setVequal toE. For an example take a look at the source forAbstractMapwhich has exactly the same pattern. You cannot create generic arrays; this is your main issue it seems.remove()fails, when you useEntry<E>instead ofEntry?