在Java中是否有可能找到具有'先验'未知维数的数组的维数?也就是说,如果一个人不知道多维矩阵的维数,如果可能的话,如何检索它呢?
答案 0 :(得分:9)
有没有人知道在Java中是否可以获得具有'先验'未知维数的数组的维数?也就是说,如果一个人不知道多维矩阵的维数,如果可能的话,如何检索它呢?
我不确定我是否理解你想要完成的事情。如果您只想知道数组中有多少元素,Anubian的答案是正确的。但我所理解的是,您想要计算给定通用数组的维数。
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);
}
}
如果那不是你想要的,我会有一个提示:长度和维度之间存在差异。
更新:我认为这与我们的要求完全无关,但Nicola在评论中问我:
这很有效,但是如果在运行时定义了维度数量(例如用户必须输入所需的维度)呢?如何定义和初始化数组?
解决方案在于一些基于光反射的黑客行为:
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());
}
}
技巧是使用给定的组件类型为N维数组构造一个Class。如果我们知道类名如何存储在最低级别,我们就可以做到这一点。其余的代码只是一个简单的无趣递归。
答案 1 :(得分:1)
假设您的矩阵名为m:
您可以通过运行
获取列数m.length;
使用Java,多维数组实际上是数组的数组。行数是可变的。假设我是0和m.length-1
之间的整数,你可以这样做:
m[i].length;
获取行中元素的数量。
答案 2 :(得分:1)
这里最初的问题是你不能首先说出以下内容:
int getNumDimensions(int[] array) { ... }
因为如果theArray
实际上是int[][]
,int[][][]
等,这会失败。但是Java中的所有数组都是Object
子类,所以这可以适用于任何数字尺寸:
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;
}
编辑:我已经尝试过针对那些疯狂的百万维数组的非递归解决方案了!
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++;
}
}
答案 3 :(得分:0)
我建议您使用仅包含一个维度的数组来管理此问题。假设有N个尺寸的尺寸:
然后您可以将数组的大小定义为:
int size = S_0*S_1*...*S_N-1;
然后你将初始化它,例如对于一个整数数组:
int[] array = new int[size];
然后要引用数组的项目(读取或写入),你有N个索引(由于N个维度):
你现在需要的是一种转换这N个索引的方法,在一个可以用作一维数组中的索引的值中,通用公式为:
这个公式基本上'跳过'正确数量的先前尺寸并指向正确的位置。这个公式可以简单地用像
这样的方法实现int read(int[] array, int[] indexes);
void write(int[] array, int[] indexes, int values);
以保持代码可读。 您也可以使用泛型类型实现此技术,因此这些方法可能适用于任何类型。
答案 4 :(得分:0)
只需直接查看初始化的代码或调用其类并检查其反射属性,即可查看其动态类型。