0

Is it possible to reuse the same function for different datatypes? So for example I have a function that converts an Integer ArrayList into an Integer array

public static int[] arrayListToIntArray(ArrayList<Integer> list) {
    int[] out = new int[list.size()];
    int count = 0;
    for (int x : list) {
        out[count] = x;
        count++;
    }
    return out;
}

However if I want to do that with a byte ArrayList I have to do this

public static byte[] arrayListToByteArray(ArrayList<Byte> list) {
    byte[] out = new byte[list.size()];
    int count = 0;
    for (byte x : list) {
        out[count] = x;
        count++;
    }
    return out;
}

So I am wondering if there is a better way than just repeating the same code with different data types and basically having an entire class of the same code? Or could I do something so it can be used for all data types?

Nightfortress
  • 43
  • 1
  • 8
  • 1
    Not if you want to return the primitive type from the wrapper. If you don't mind returning a `Byte[]` or `Integer[]` then you can just call `list.toArray();` – Elliott Frisch Jun 01 '17 at 21:18
  • It was just an example I was using not specific to that function but thanks anyway. – Nightfortress Jun 01 '17 at 21:24
  • Yeah, in general for performance and Java-y reasons, you don't want to do this for primitive types. It's best to split up Java into primitive/array based stuff and Object/Generics based stuff. You can get around this using Number.class, but there is a reason there are primitive versions of things like streams and functions. If you are coming from C#, this is a significant difference. – Novaterata Jun 01 '17 at 21:34
  • You are looking for Generics. See [JAVA Generics](https://docs.oracle.com/javase/tutorial/java/generics/types.html) – itay Jun 01 '17 at 21:20

2 Answers2

3

Yes you can. It's called Generics.

public static <T> T[] arrayListToIntArray(ArrayList<T> list) {
    T[] out = (T[]) new Object[list.size()];
    int count = 0;
    for (T x : list) {
        out[count] = x;
        count++;
    }
    return out;
}

Update:

You can not instantiate a Generic Type so you can pass also another argument that will be the type, take a look at this.

public static <T> T[] arrayListToIntArray(ArrayList<T> list, Class<T> t ) {
        T[] out = (T[]) Array.newInstance(t, list.size());
        int count = 0;
        for (T x : list) {
            out[count] = x;
            count++;
        }
        return out;
    }
epinal
  • 1,063
  • 10
  • 24
  • Could you explain why I am getting an "illegal start of type" error with that code? – Nightfortress Jun 01 '17 at 21:35
  • Did it solved your issue? Please mark the answer as solution if it did or let me know if you have more questions. Thanks @Nightfortress – epinal Jun 15 '17 at 16:42
1

Changing the typing in your method to Generics, you can write this

public static <T> T[] arrayListToArray(ArrayList<T> list, Class<T> type) {
    @SuppressWarnings("unchecked")
    final T[] out = (T[]) Array.newInstance(type, list.size());
    int count = 0;
    for (T x : list) {
        out[count] = x;
        count++;
    }
    return out;
}

and then use it like this

public static void main(String[] args) {
    ArrayList<Integer> intList = new ArrayList<>();
    intList.add(13);
    intList.add(37);
    intList.add(42);
    Integer[] intArray = arrayListToArray(intList, Integer.class);

    ArrayList<Byte> byteList = new ArrayList<>();
    byteList.add((byte) 0xff);
    byteList.add((byte) 'y');
    byteList.add((byte) 17);
    Byte[] byteArray = arrayListToArray(byteList, Byte.class);

    System.out.println(Arrays.toString(intArray));
    System.out.println(Arrays.toString(byteArray));
}

Output:

[13, 37, 42]
[-1, 121, 17]
Angelo D.
  • 25
  • 8