1

Been doing well with Java until generics. I'm having a hard time converting this queue to use generics that will accept any data type.

I don't understand why item cant be converted to int when item should represent "any" data type.

An answer plus a little explanation on generics would be useful, as I need to create a remove function as well.

private int initialCapacity = 10;
private int size = 0;
private int[] content;

public static <E> void add(E item) {
    int size = 0;
    int[] content;

    // If we run out of space in the array
    if (size == content.length) {

        // 1) Create a new, larger array (2x)
        int[] newArray = new int[content.length * 2];

        // 2) Copy the content from the old array to the new one
        for (int c = 0; c < content.length; c++) {
            newArray[c] = content[c];
        }

        // 3) Let the old array point to the new array
        content = newArray;
    }

    //Add the item to the content of the array list
    content[size] = item;
    size++;
}
blacktide
  • 10,654
  • 8
  • 33
  • 53
jjflyV7
  • 55
  • 1
  • 6

3 Answers3

3

Let's begin from the top. E is a type parameter, so we should first figure out its scope. Typically, for a queue, the type parameter applies to the queue as a whole (and not just a single add) operation, since we'd want the queue to have consistent types. Thus, begin by declaring your class as:

public class YourQueue<E> {
    ...
}

and remove the <E> from the method declaration for add, making it public void add(E item). Not sure why you've declared it static, since it should add to a given queue.

Thirdly, if you're going to use an array to store elements of a YourQueue<E>, it shouldn't be an integer array, since all sorts of objects are not convertible to integers. It should be an array declared as E[].

nanofarad
  • 40,330
  • 4
  • 86
  • 117
  • I still receive the the error on item on this line " content[size] = item; " in my add: cannot convert from E to int – jjflyV7 May 05 '16 at 02:05
0

In Java, generics don't support primitive types. Simply use Integer instead of int, for your applications it will mostly be the same.

See here too: Why don't Java Generics support primitive types?

Community
  • 1
  • 1
Lorenzo Barbagli
  • 1,241
  • 2
  • 16
  • 34
0

The simple answer to your question is that an int is a basic data type (or primitive), and an object cannot be converted into a basic data type automatically unless it is a wrapper class that is wrapping that particular basic data type. In this case the wrapper class is Integer. Based on your goal of making a queue, converting item to an int is not what you want, instead you want to use an array that can hold item in it rather than int.

The code content[size] = item; says to assign the size cell of content to the value of item. If item is not an Integer then this will fail. Since, at compile time, the type of item is ambiguous this will fail. You can solve this problem by replacing your int array with an Object array, since every class in java has Object as a parent or ancestor.

A more verbose answer follows:

I think that your question could be rephrased like this:


"I created a queue implementation for the primitive type int, but I'm not sure how to use generics so that the queue can use generics.

Here is the original integer queue implementation with just the add method (working code):

public class IntQueue {
   private int initialCapacity = 10;
   private int size = 0;
   private int[] content = new int[initialCapacity];

   public void add(int item) {

      // If we run out of space in the array
      if (size == content.length) {

          // 1) Create a new, larger array (2x)
          int[] newArray = new int[content.length * 2];

          // 2) Copy the content from the old array to the new one
          for (int c = 0; c < content.length; c++) {
              newArray[c] = content[c];
          }

          // 3) Let the old array point to the new array
          content = newArray;
      }

      //Add the item to the content of the array list
      content[size] = item;
      size++;
   } 
}

Here is the modified queue implementation with just the add method to use Generics:

public class GenericQueue<E> {
   private int initialCapacity = 10;
   private int size = 0;
   private int[] content = new int[initialCapacity];

   public static <E> void add(E item) {
      int size = 0;
      int[] content;

      // If we run out of space in the array
      if (size == content.length) {

          // 1) Create a new, larger array (2x)
          int[] newArray = new int[content.length * 2];

          // 2) Copy the content from the old array to the new one
          for (int c = 0; c < content.length; c++) {
              newArray[c] = content[c];
          }

          // 3) Let the old array point to the new array
          content = newArray;
      }

      //Add the item to the content of the array list
      content[size] = item;
      size++;
   } 
}

This gives the error

GenericQueue.java:26: error: incompatible types: E cannot be converted to int
      content[size] = item;
                      ^
  where E is a type-variable:
    E extends Object declared in method <E>add(E)
1 error

For some reason, just using a generic method header didn't make the code work. What am I missing?"


Answer:

There are a few of things that you are missing. First, your add method shouldn't be static, otherwise you will always only have one list.

So:

   public static <E> void add(E item) {

should be:

   public void add(E item) {

Second, you have two arrays called content, one that is the field content, and one that is a local variable inside of add. The local variable should be removed from your code so that it doesn't mask the field. Similarly, you have a local variable for size that should be removed from your add method.

So:

   public static <E> void add(E item) {
      int size = 0;
      int[] content;

should become:

   public void add(E item) {

You are missing the changes to your code that expect your data to be an int. When generalizing your code, you need to think about what part of the code that is being generalized. In this case, you want to make a list that will work for any one type of data. Your initial list used an array of integers to hold the data, so that array of integers will need to be changed to an array of any type, i.e. your generic symbol. In your case E. That means that all cases of code that have an integer array should be converted to code that has an E array. The only exception to this is for the instantiation of an array, since you can't use a Generic to instantiate an array, instead you need to use Object.

The parts that use the int array are:

private int[] content = new int[initialCapacity];
int[] newArray = new int[content.length * 2];

These can be changed as follows:

private E[] content = new Object[initialCapacity];
E[] newArray = new Object[content.length * 2];

You may be asking what the difference between making a list of Object vs. a list of generic type. Since Object is a parent of all class types, a list of Object could hold data of different types of objects such as Integers and Strings, while a generic list will have to choose one type of object, and all objects will have to be of that type. Having this kind of guarantee makes it easier to use the list because you don't have to check the type of the item in the list before using it.

cooplogic
  • 31
  • 2