Reputation: 562
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
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
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
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
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