1

I'm trying to speed up an existing implementation of an algorithm in order to parallelize it on the GPU, but to do that all I need to convert all datatypes to primitives.

I have a collection of char-arrays Collection<char[]> how can I transform it into an array of char-arrays char[][]?

I tried final char[][] kernelFeatures = (char[][]) features.toArray();

However, I am getting an error message java.lang.ClassCastException: class [Ljava.lang.Object; cannot be cast to class [[C ([Ljava.lang.Object; and [[C are in module java.base of loader 'bootstrap').

t-bone
  • 184
  • 2
  • 14

2 Answers2

1

Problem

The reason you can't use Collection#toArray() and cast the result to char[][] is because:

The returned array's runtime component type is Object.


Solutions

Pre Java 11

You can use Collection#toArray(T[]) which allows to to specify the component type of the array.

Collection<char[]> collection = ...;
char[][] array = collection.toArray(new char[0][]);

To understand why you don't need to specify the second dimension, remember that two-dimensional arrays in Java are simply one-dimensional arrays where each element is an array. See these Q&As for more information:

Regarding the use of 0 as the first dimension, note that using 0 is not required; you can use any valid length you want (e.g. collection.size()). The reason for using 0, however, is that it's supposedly more efficient, at least when using an ArrayList on HotSpot 8:

I'm not sure if it's more efficient in other versions, other JVM implementations, or for other Collection implementations.

Java 11+

If you're using Java 11+ then there's an alternative solution: Collection#toArray(IntFunction).

Collection<char[]> collection = ...;
char[][] array = collection.toArray(char[][]::new);

Which, as a lambda expression, would look like:

Collection<char[] collection = ...;
char[][] array = collection.toArray(i -> new char[i][]);

Manual Copy

Both of the #toArray methods ultimately do something similar to:

Collection<char[]> collection = ...;

char[][] array = new char[collection.size()][];
int index = 0;
for (char[] element : collection) {
  array[index++] = element;
}

Though you should use one of the #toArray methods because that allows the Collection implementation to use any optimizations it can. For example, the ArrayList class uses the System#arraycopy method.

Slaw
  • 37,820
  • 8
  • 53
  • 80
  • Thanks, `char[][] array = collection.toArray(new char[0][]);` solved it for me. Could you elaborate on how/why it works and why the char[][] has to have a 0 as a first index? – t-bone Nov 06 '19 at 12:03
  • 1
    Updated my answer. – Slaw Nov 06 '19 at 15:52
0

Try this:

  List<char[]> list = List.of(new char[] { '1', '2'
      }, new char[] { '3', '4'
      }, new char[] { '6', '7'
      });
      char[][] array = list.stream().toArray(char[][]::new);
      System.out.println(Arrays.deepToString(array));

or to print out with a for loop

    for (char[] c : array) {
        System.out.println(Arrays.toString(c));
    }
WJS
  • 36,363
  • 4
  • 24
  • 39