Mazino
Mazino

Reputation: 562

Java variable number of dimensions in an array

Is there a possible way to create an array with a variable number of dimensions?

For example,

int x = 3;
// becomes
int[][][] array = new int[3][3][3];

//and
int y = 4;
//becomes
int[][][][] xray = new int[4][4][4][4];

Part of the reason my examples are so indirect is because I have no idea how one would do something like this.

If I have a variable I would like to create an array with the same number of dimensions as said variable

Upvotes: 3

Views: 2321

Answers (4)

potato
potato

Reputation: 1123

public Object createMultidimensionalArray(int dimLength){
    int[] lengths = new int[dimLength];
    for(int i = 0; i < dimLength; i++)
        lengths[i] = dimLength;
    return Array.newInstance(int.class, lengths);
}

Usage example:

int[][][] array3D = (int[][][]) createMultidimensionalArray(3);
System.out.println(Arrays.deepToString(array3D));

Output:

[[[0, 0, 0], [0, 0, 0], [0, 0, 0]], [[0, 0, 0], [0, 0, 0], [0, 0, 0]], [[0, 0, 0], [0, 0, 0], [0, 0, 0]]]

Explanation:

The function Array.newInstance(Class<?> componentType, int... dimensions) takes as input the wanted array type and lengths of all dimensions.

dimensions is an array that tells the function what size each dimension should be. To get a 4x4x4x4 array, the following code works:

int[] dimensions = {4, 4, 4, 4};
Object arrObj = Array.newInstance(int.class, dimensions);
int[][][][] arr = (int[][][][]) arrObj;

Array.newInstance(...) returns an Object which can be easily converted to the correct type.

Upvotes: 0

ajb
ajb

Reputation: 31699

You can't do this directly, but you can simulate it with a 1-dimensional array.

Suppose you have a 2-dimensional array with 3 rows and 4 columns. You could implement this as an array of 12 elements, and write a get routine to get the A[i,j] element like this:

int[] A = new int[12];

int get(int i, int j) {
    return A[4 * i + j];
}

Of course you could write a set method to set an element of the array in the same way.

Moving on to a 3-dimensional array whose dimensions are 3x4x5, you could do something similar:

int[] A = new int[60];

int get(int i, int j, int k) {
    return A[4*5*i + 5*j + k];
}

or a 4-dimensional 3x4x5x6 array:

int[] A = new int[360];

int get(int i, int j, int k, int m) {
    return A[4*5*6*i + 5*6*j + 6*k + m];
}

And so on... you should be able to see the pattern.

Once you've grasped that, it shouldn't be hard to write a class for an array that takes a variable number of dimensions. The get and set methods could take an int... parameter for a variable number of indexes, and the constructor could similarly take an int... to specify the dimensions. The class would have a private 1-dimensional array whose length is the product of all the dimensions. The get and set methods should check each index to make sure it's >= 0 and less than the corresponding dimension, and throw an exception otherwise.

This is how "true" multi-dimensional arrays are implemented under the hood in most languages that support them (Java is not one of those; it only has 1-dimensional arrays whose elements can be references to other 1-dimensional arrays). It's called "row-major order". See https://en.wikipedia.org/wiki/Row-_and_column-major_order for more information (including the generalized formula).

Upvotes: 5

Deyu瑜
Deyu瑜

Reputation: 544

I try to make this , but return type is Object[] ^^"

public Object[] MakeArray(int s){
  ArrayList l = new ArrayList<>(Collections.nCopies(s, 0));
  for (int i = 1; i < s; i++)
    l = copy(l,s);
  return l.toArray();
}
public ArrayList copy (ArrayList l,int s){
    ArrayList<ArrayList> ret = new ArrayList<>(s);
    for (int i = 0; i < s; i++) 
        ret.add(new ArrayList(l));
    return ret;
}

Arrays.toString(MakeArray(2)) = "[[0, 0], [0, 0]]"
Arrays.toString(MakeArray(3)) = "[[[0, 0, 0], [0, 0, 0], [0, 0, 0]], [[0, 0, 0], [0, 0, 0], [0, 0, 0]], [[0, 0, 0], [0, 0, 0], [0, 0, 0]]]"

Upvotes: 0

Comfort Chauke
Comfort Chauke

Reputation: 126

Short answer you can't. Reason: there is no instance in the world of maths where such a construct could be optimum for anything so the Prophets (K&R and all the good ppl who invent code) left such to the developer who needs it.

But here is my 2 cents: I assume you want to initialize your engine...

engine.init(n);

where n is your dimension. Then be able to put and get things from it.

engine.get(a1,a2,a3,...);
engine.put(val,a1,a2,a3...);

Consider a class like this

public class Engine{
private HashMap<Integer[],Object> storage;
private int dimension=1;
private set<integer[]> keys;
public void init(int n){
dimension=n;
//other initialization task;
}

public Object get(int... a){//use var args
integer[] key=findInkeySet(a);
return storage.get(key);
}

public void put(Object val, int... a){
keys.add(a);
storage.put(a,val);
}
}

ofcause there is need for exception handling and all the other generic coding stuf

Upvotes: 1

Related Questions