How do I implement generics <E> in a linked List? - java

I have been trying to create a linked list that uses generics to return a data type of the user's choosing. The problem is that my method public E get(int sub)
is not recognizing my return cursor.contents as a type E generic.
public E get(int sub)
{
Node cursor = head; //start at the beginning of linked list.
for (int c = 1; c <= sub; c++)
{
cursor = cursor.next; //move forward by one.
}
return cursor.contents;//return the element that the cursor landed on.
}
public class Node <E>
{
public E contents;
#SuppressWarnings("rawtypes")
public Node next = null; //points to the next node
//a method has no return type and has the same name as the class
public Node(E element)
{
this.contents = element;
}
}
as I have shown above the contents parameter is declared as type E in the Node, but the get method will not recognize cursor.contents as a proper return type.
The system recomments that I either change the return type to Object, which is not an option. Or I change contents to a type E which has already been done, but it still gives me a compilation error.

That's because you need to change it to:
public E get(int sub)
{
Node<E> cursor = head; //you forgot the generics here
for (int c = 1; c <= sub; c++)
{
cursor = cursor.next;
}
return cursor.contents;
}
public class Node <E>
{
public E contents;
public Node<E> next = null; //you also even suppressed the raw type here
public Node(E element)
{
this.contents = element;
}
}

You're not setting the generic type on the declaration of your Node cursor variable. What happens when you change that to Node<E> cursor.
Also, you're not providing context of the linked list class itself - that's where the generic <E> should be declared.

In your method
public E get(int sub)
You initialize a cursor as a Node instead of Node<E>.
Node cursor = head; //start at the beginning of linked list.
This will cause the element type to be Object which is what you get when you write
return cursor.contents;
To Solve:
Either use a Node<E> or explicitly cast the return to E

Are these part of a class with a typed parameter, such as MyLinkedList<E>? The problem may be that you added a <E> type parameter to the Node class as well, which may refer to a different class E that is not necessarily the same E referenced by the outer class. Try changing Node <E> to Node.and see if it works.

Related

How to return generic methods?

I'm doing my homework right now and I stumbled on a, probably pretty easy, 'problem'.
I have to build a stack and I need to complete the following method:
public E top()
{
if(!isEmpty()) {
/*
* return top element
* which would be st[pos-1]
*/
}
return null;
}
I use
//to save elements
private Object[] st;
//for position in array
private int pos = 0;
I tried to return my array, but it tells me "Cannot convert from Object to E". Now I don't know how to continue.
//edit: my constructor
public Stack(int size)
{
st = new Object[size];
//st = new E[size]; doesn't work
}
You need to cast:
E element = (E) st[pos-1];
You will get an unchecked cast warning, though. This is safe to suppress, provided you ensure that only instances of E are added to the array.
void add(E element) {
st[pos++] = element;
}
(And that is pretty much what java.util.ArrayList does, btw)
Your Array should be of type E
private E[] st;

Cascading Generic Type declarations in Java

I am having a hard time finding this anywhere if this is a common problem but I am dealing with what is essentially a cascading type problem.
public class Graph<E> {
private LinkedList<Node<E>> nodes;
public Graph() {
this.nodes = new LinkedList<>();
}
public E[] getNodes() {
ArrayList<E> list = new ArrayList<>();
for (Node<E> node : nodes)
list.add(node.getObject());
return list.toArray(new E[0]); // any way to make this line work?
}
// other important stuff
}
I want to do something like this, however I can't instantiate the generic array this way. Where the getNodes() returns the content of the Nodes, not the Nodes themselves, but I can't figure out how.
I was thinking that the Node generic being defined by the Graph generic would mean that the Node class always has the same type as the Graph class. Is that not the case?
The Node class looks like
public class Node<E> {
private LinkedList<Edge> edges;
private E obj;
public E getObject() {
return obj;
}
// other useful stuff
}
Thanks for any help!
EDIT: all that is needed now is to make the returned Array of the right type. Is there a way to get an Array from an ArrayList that has a generic type assignment?
You need some form of reification of E in your getThings method.
If you want to keep the signature of getThings as it is, you can add a construtor parameter to provide the actual class E. With that class you can create an array to pass to the toArray(E[]) method of List<E>
private final Class<E> type;
private final List<E> list;
public CustomClass(Class<E> type) {
this.type = type;
this.list = new ArrayList<>();
}
#SuppressWarnings("unchecked")
public E[] getThings() {
Object[] reference = (Object[]) Array.newInstance(type, list.size());
return (E[]) list.toArray(reference);
}
Someone else came up with an answer that did not work but gave me an idea that ended up working, but they also put it in the comments section of the question so I will reiterate here and answer my own question.
This code works to solve the problem. I more or less lifted the logic from the ArrayList source code for their toArray(E[] a) function (with some of the meat of it cut out of course).
#SuppressWarnings("unchecked")
public E[] getNodes(E[] a) {
int size = nodes.size();
// creates an empty array of the right size and type
E[] arr =(E[]) java.lang.reflect.Array
.newInstance(a.getClass().getComponentType(), size);
// fills that array with the correct data
for (int i = 0; i < size; i++)
arr[i] = nodes.get(i).getObject();
return arr;
}
Look at the ArrayList source code in order to see some logic that goes a step farther and accomplishes the same task in a way that is also Thread safe.

How do I set a generic object in my array to 0/null?

I have an array that in my class declaration holds objects of generic type (later on, I will add <Integer> type objects). I want to delete the index at currentSize (which is an int). Eclipse complains by saying "Type mismatch: cannot convert int to E" regarding to the line
list[currentSize] = null;
Here's my code:
...
private int currentSize, maxCapacity;
...
public ArrayABC(){
currentSize = 0;
maxCapacity = 20;
list = (E[]) new Object[maxCapacity];
}
...
public E removeLast(){
if(currentSize == 0)
return null;
list[currentSize] = null;
currentSize--;
return list[currentSize];
}
Also note that after I try to assign the list[currentSize] as a return value. Do I have to cast it to <E> while doing so (very last line of the code)?
I guess a better way of putting this is, how do I destroy the object at location = currentSize?
Thank you for your help and support in advance!
It all depends on how your list is declared.
Also since you cast it to type parameter E you must use this type parameter somewhere in your class declaration like this: <E>
Below compiles for me just fine:
public class ArrayABC<E> {
private int currentSize, maxCapacity;
private E[] list;
public ArrayABC(){
currentSize = 0;
maxCapacity = 20;
list = (E[]) new Object[maxCapacity];
}
public E removeLast(){
if(currentSize == 0)
return null;
list[currentSize] = null;
currentSize--;
return list[currentSize];
}
}
The only snag is that Eclipse is highlighting:
list = (E[]) new Object[maxCapacity];
as warning with unsafe access, but there is no clean way to create instance of any object with type E due to type erasure.

creating instance using self as argument

creating a doubly linked list with one node that points to itself
public DList(){
Dnode sentinel= new DNode(sentinel, null, sentinel);
}
for reference, Dnode constructor takes DNode(Dnode p, Object 0, Dnode n)
Is this valid code?
No, this is not valid.
You can't cant use sentinel variable in the expression that defines it.
You can however have a constructor, which makes the previous and next elements be itself (this):
class DList {
DList previous, next;
public DList() {
previous = this;
next = this;
}
}

Getting a compilation error when implement interface comparable

I am trying to using the compareTo method for a generic Node type E.
I have already bound E to Comparable
public class LinkedList<E extends Comparable<E>> {
// ----------------------------------------------------------
// Implementing the doubly linked nodes (static nested class)
// ----------------------------------------------------------
private static class Node<E extends Comparable<E>> {
This method isSorted is implemented within the LinkedList class, the Node class is within the Linkedlist class.
I keep getting a compilation error "The method compareTo(LinkedList.Node) is undefined for the type LinkedList.Node"
I believe that only pops up when E is not extending Comparable, in my case it is.
Any help?
public boolean isSorted( ){
if(!isEmpty()){
Node<E> temp = head;
boolean local = true;
int x=0;
while (temp.next != null){
x=temp.compareTo(temp.next);
if(x<0){
temp = temp.next;}
else {return local;}
}
return local;}
else{ throw new IllegalArgumentException();}
}
I checked this thread already, How to compare generic nodes in a linked list using Comparable?
It didn't help.
Thank you in advance
Mjall2
You're trying to compare the nodes, when it's only the values inside the nodes that are Comparable. Instead of temp.compareTo(temp.next), you probably want something like temp.value.compareTo(temp.next.value).

Categories