用Java抽象数组的维数

在Java中,不同维度的数组具有不同的类型。 因此,将int[]作为参数的方法不能采用int[][]int[][][] 。 我有很多代码,我创建的方法非常相似,但是对于数组的维度。 有没有办法处理任意维度的数组,从而抽象出这个常见的function?

如果你愿意放弃类型安全,你可以通过一点递归(这里不出意,对吧?)和reflection来做到这一点。

我们的想法是以一种递归方式编写方法,直到数组只有一个维度。 一旦你处于单维层面,就做好工作; 否则,递归调用自己,并在必要时汇总先前级别的结果。

这是一个快速演示:

 import java.util.*; import java.lang.*; import java.lang.reflect.Array; class Main { public static int sumArray(Object array) { Class type = array.getClass(); if (!type.isArray()) { throw new IllegalArgumentException("array"); } Class ct = type.getComponentType(); int res = 0; int len = Array.getLength(array); if (ct.isArray()) { for (int i = 0 ; i != len ; i++) { res += sumArray(Array.get(array, i)); } } else { for (int i = 0 ; i != len ; i++) { res += Array.getInt(array, i); } } return res; } public static void main (String[] args) throws java.lang.Exception { int[] a = new int[] {1,2,3,4,5,6,7,8,9,10}; int aa[][] = new int[][] {{1,2},{3,4},{5,6}}; int aaa[][][] = new int[][][]{{{1,2},{3,4},{5,6}},{{7,8},{9,10},{11,12}}}; System.out.println(sumArray(a)); System.out.println(sumArray(aa)); System.out.println(sumArray(aaa)); } } 

我要说的是,你能做的最接近的事情就是制作一些过载方法,这些方法采用数组的所有可用维度,并让每个方法调用一个具有大量逻辑的常用方法。

 public void method ( int [] i ) { //1-d array //logic } public void method ( int [][] i) { //2-d array for (int [] j : i) { method(j); } } public void method ( int [][][] i) { // 3-d array for ( int [][] j : i ) { method(j); } } 

…等等

最简洁的答案是不。 答案很长很抱歉,但没有。 由于Java处理数组的方式,这两者基本上是不同的类型,并且没有任何好方法可以用单个代码处理任何维度的数组。

答案是不! 但你可以用线性arrays做任何你想做的事….想一想

您可以通过将其实现隐藏在类中来实现多维数组(原谅或更正我的Java语法,我不是Java编码器):

 class MultidimensionalArray { // Implement N-dimensional 0-origin array of  int[] dimensions; Type[] body; MultidimensionalArray(index1: int) { dimensions=new int[1]; dimensions[0]=index1; body=new Type[index1]; } MultidimensionalArray(index1: int, index2: int) { dimensions=new int[2]; dimensions[0]=index1; dimensions[1]=index2; body=new Type[index1*index2]; } MultidimensionalArray(int[] indexes) { size=1; dimensions=indexes; for(int i=0;i 

您可以通过调用其consructor来初始化它,并通过传入一个整数数组作为索引集来访问元素。 有点笨拙但有效:

 int[] mydimensions={2,3,5}; MyArray MultidimensionalArray=new MultidimensionalArray(mydimensions); ... int[] indexset={1,2,4}; MyArray.Put(indexset,22); ... indexset = {0,1,3}; ... MyArray.Get(indexset) ... 

我为不需要索引集的1D和2D数组添加了便利函数,而是使用单个参数作为索引。 很容易推广到维度K的数组。您还可以添加函数来创建不同大小的索引集。

所有这些都是以一些开销为代价的。

答案是“可能没有”。 正如其他答案所指出的那样,具有不同维度的数组类型不是分配兼容的。 但是,有一条可能的出路。

int[] int[][]int[][][]类型都是Object子类型。 并且(例如) int[][]实际上是int[]实例的数组。 因此, 对于某些计算 ,可能会执行以下操作:

 public void calc(Object array) { if (array instanceof int[]) { calc((int[]) array); } else if (array instanceof int[][]) { for (a int[] : (int[][]) array) { calc(a); } } else if (array instanceof int[][][]) { for (a int[][] : (int[][][]) array) { for (a2 int[] : a) { calc(a2); } } } else { throw new ClassCastException(...); // or something more appropriate } } public void calc (int[] array) { // do the calculation } 

注意事项:

  • 这仅在计算以这种方式工作时有效,

  • 你必须为每种方法重复这个丑陋的样板,并且

  • 样板实际上可能比使用三种不同的方法更糟糕。

现在,根据计算(和性能要求),您可以通过在对象中进行计算来概括代码,该对象可以传递给通用的“应用于所有元素”方法; 例如

 public interface Calc { public void calc(int i); } ... public void doCalc(Object array, Calc calculator) { // as above } public void doCalc(int[] array, Calc calculator) { for (int i : array) { calculator.calc(i); } } 

……但是仍然有很多样板……你会受到性能的影响。