Getting unknown number of dimensions from a multidimensional array in Java

前端 未结 5 1583
天命终不由人
天命终不由人 2020-12-18 05:23

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

相关标签:
5条回答
  • 2020-12-18 05:40

    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.

    0 讨论(0)
  • 2020-12-18 05:46

    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.

    0 讨论(0)
  • 2020-12-18 05:46

    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:

    size of the N dimensions

    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):

    indexes to refer the array

    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:

    how transform the N indexes in one index for the one-dimensional array

    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.

    0 讨论(0)
  • 2020-12-18 05:50

    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++;
        }
    }
    
    0 讨论(0)
  • 2020-12-18 05:56

    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.

    0 讨论(0)
提交回复
热议问题