Is it possible in Java to find the number of dimensions of an array with an \'a priori\' unknown number of dimensions? That is, if one doesn\'t know the number of dimensions
Just look at its dynamic type either by looking directly in your code where it is initialized or by calling its class and examining its reflected attributes.
Assuming your matrix is called m:
You can get the number of columns by running
m.length;
With Java, multidimensional arrays are actually arrays of arrays. The number of rows is variable. Assuming i is an integer between 0 and m.length-1
you can do:
m[i].length;
To get the number of elements in the row.
What I can suggest you is to manage this issue by using an array with only one dimension. Suppose to have N dimensions of sizes:
Then you can define the size of your array as:
int size = S_0*S_1*...*S_N-1;
Then you will initialize it, for instance for an array of integers:
int[] array = new int[size];
Then to refer to an item of the array (to read or write it), you have N indexes (because of N dimensions):
What you need now is a way to transform this N indexes, in one single value that can be used as an index in the one-dimensional array, the generic formula is:
Basically this formula 'skips' the correct number of previous dimensions and points to the right location. This formula can be simply implemented in methods like
int read(int[] array, int[] indexes);
void write(int[] array, int[] indexes, int values);
in order to keep the code readable. You may also implement this technique using a generic type, so the methods might work for any type.
The initial problem here is that you can't begin by saying something to the effect of:
int getNumDimensions(int[] array) { ... }
Because this would fail if theArray
was actually an int[][]
, int[][][]
, etc. But all arrays in Java are Object
subclasses, so this can work for any number of dimensions:
int getNumDimensions(Object array) {zz
if (array instanceof Object[]) {
// array has at least 2 dimensions (e.g. int[][])
return getNumDimensions(((Object[]) array)[0]) + 1;
}
if (array.getClass().isArray()) {
// array is, by process of elimination, one-dimensional
return 1;
}
return 0;
}
Edit: I've tried my hand at a non-recursive solution for those crazy million-dimensional arrays!
int getNumDimensions(Object array) {
Object tmp = array;
int nDimensions = 0;
while (True) {
if (array instanceof Object[]) {
// tmp has at least 2 dimensions (e.g. int[][])
tmp = ((Object[]) array)[0];
}
else if (tmp.getClass().isArray()) {
// tmp is, by process of elimination, one-dimensional
return nDimensions + 1;
}
nDimensions++;
}
}
Does anyone know if it is possible in Java to get the number of dimensions of an array with an 'a priori' unknown number of dimensions? That is, if one doesn't know the number of dimensions of a multidimensional matrix, how could it be retrieved, if possible?
I'm not quiet sure if I understood correctly what you are trying to accomplish. If you just want to know how many elements are there in array, Anubian's answer is correct. But what I understood is that you want to calculate number of dimensions of a given general array.
public class Test {
public static int getNumberOfDimensions(Class<?> type) {
if (type.getComponentType() == null) {
return 0;
} else {
return getNumberOfDimensions(type.getComponentType()) + 1;
}
}
public static void main(String[] args) {
System.out.println(getNumberOfDimensions(int[][][].class) == 3);
System.out.println(getNumberOfDimensions(int[][].class) == 2);
System.out.println(getNumberOfDimensions(int[][][][].class) == 4);
System.out.println(getNumberOfDimensions(int.class) == 0);
}
}
If that's not what are you looking for, I'd have a hint: there is a difference between a length and dimension.
Update: I think this is completely irrelevant to what we were asked, but Nicola asked me in the comments:
This works perfectly, but what about if the number of dimensions is defined at run-time (for instance the user has to input the desired amount of dimensions)? How you could define and initialize the array?
The solution lies in some light reflection-based hacking:
import java.lang.reflect.Array;
public class Test {
public static Class<?> getArrayType(Class<?> componentType, int dimensions) throws ClassNotFoundException {
if (dimensions == 0) {
return componentType;
}
String rawName = componentType.getName();
switch (rawName) {
case "byte": rawName = "B"; break;
case "char": rawName = "C"; break;
case "double": rawName = "D"; break;
case "float": rawName = "F"; break;
case "int": rawName = "I"; break;
case "long": rawName = "J"; break;
case "short": rawName = "S"; break;
case "boolean": rawName = "Z"; break;
default:
rawName = "L" + rawName + ";";
break;
}
for (int i = 0; i < dimensions; i++) {
rawName = "[" + rawName;
}
return Class.forName(rawName);
}
public static Object createArray(Class<?> componentType, int dimensions, int length) throws NegativeArraySizeException, ClassNotFoundException {
if (dimensions == 0) {
return null;
}
Object array = Array.newInstance(getArrayType(componentType, dimensions - 1), length);
for (int i = 0; i < length; i++) {
Array.set(array, i, createArray(componentType, dimensions - 1, length));
}
return array;
}
public static void main(String[] args) throws ClassNotFoundException {
Object object = createArray(Integer.class, 3, 10);
System.out.println(object.getClass());
}
}
The trick is to construct a Class for N-dimensional array using a given component type. We can do that if we know how class names are stored on the lowest level. Rest of the code is just a simple not-interesting recursion.