I need to be able to have an n-dimensional field where n is based on an input to the constructor. But I'm not even sure if that's possible. Is it?
-
1Can you clarify what it is you want? It's easy to read about four or five different requirements into your question... – T.J. Crowder Jan 22 '11 at 22:12
3 Answers
Quick solution: you could approximate it with a non-generic ArrayList
of ArrayList
of ... going as deep as you need to. However, this may get awkward to use pretty fast.
An alternative requiring more work could be to implement your own type using an underlying flat array representation where you calculate the indexing internally, and providing accessor methods with vararg parameters. I am not sure if it is fully workable, but may be worth a try...
Rough example (not tested, no overflow checking, error handling etc. but hopefully communicates the basic idea):
class NDimensionalArray {
private Object[] array; // internal representation of the N-dimensional array
private int[] dimensions; // dimensions of the array
private int[] multipliers; // used to calculate the index in the internal array
NDimensionalArray(int... dimensions) {
int arraySize = 1;
multipliers = new int[dimensions.length];
for (int idx = dimensions.length - 1; idx >= 0; idx--) {
multipliers[idx] = arraySize;
arraySize *= dimensions[idx];
}
array = new Object[arraySize];
this.dimensions = dimensions;
}
...
public Object get(int... indices) {
assert indices.length == dimensions.length;
int internalIndex = 0;
for (int idx = 0; idx < indices.length; idx++) {
internalIndex += indices[idx] * multipliers[idx];
}
return array[internalIndex];
}
...
}

- 114,404
- 31
- 268
- 329
-
I agree with with your first assessment, Collections are the way to go. However, your solution may be cleaner than the mess of generic specifications that could result from doing it that way (i.e. List
- >>>)
-
1@John, it wouldn't even work with generics as you can't assemble/change generic type parameters runtime. I.e. with 3 dimensions the outermost list would need to be a `List
- >>`, but with 7 dimensions a `List
- >>>>>>` is required. Similarly, all the elements (i.e. the inner lists) would be of different types - one just can't handle this in code in a uniform way.
Here's a nice article that explains how to use reflection to create arrays at run-time: Java Reflection: Arrays. That article explains how to create a one-dimensional array, but java.lang.reflect.Array
also contains another newInstance
method to create multi-dimensional arrays. For example:
int[] dimensions = { 10, 10, 10 }; // 3-dimensional array, 10 elements per dimension
Object myArray = Array.newInstance(String.class, dimensions); // 3D array of strings
Since the number of dimensions is not known until runtime, you can only handle the array as an Object
and you must use the get
and set
methods of the Array
class to manipulate the elements of the array.

- 69,683
- 7
- 133
- 150
-
I'm not sure if using get/set isn't too slow to be usable. You can always cast it to Object[] or to a primitive array in case you're dealing with the last dimension and the members are primitive. However, I can't imagine how to use such an unknown-dimensional array. Even simple iteration through it means using an unknown number of nested loops. I'd consider creating o 1-dimensional array instead and compute the index using Horner scheme like `i1 + dim1 + (i2 + dim2 * (....))`, which can be done using a simple loop. – maaartinus Jan 22 '11 at 23:26