Java通用原始类型n维数组

3

我需要将一个原始的二维数组传递给一个过滤程序。无论数组的类型是什么,过滤算法(中值滤波)都是相同的。有没有一种通用的方式可以以通用的方式传递任何类型的数组,或者应该使用不同的数组类型重载同一个函数。在第二种情况下,相同的代码将不得不为不同的数据类型重复。

int[][] medianfilter(int[][] arr){ ... }
float[][] medianfilter(float[][] arr){ ... }

有没有一种方法可以将上述代码变成通用的,而不是在每个重载函数中都重复编写medianfilter代码?
3个回答

1

以通用方式传递并将其保留为原始数组的唯一方法是使用Object。就我个人而言,我会重载它,并将其视为使用原始类型的成本。

为了避免在算法中重复代码(如果代码很多),您可以创建一个名为DoubleAlgorithm的抽象类,其中包含像double getElement(int i, int j)handleResult(double result)这样的抽象方法,然后编写非常小的子类,每个子类对应一种原始类型。

让我举个例子来解释一下(假设算法是将数字相加)。

public int filter(int [][] values) {
   IntAlgorithm algo = new IntAlgorithm(values);
   algo.run();
   return algo.getResult();
}
public double filter(double [][] values) {
   DoubleAlgorithm algo = new DoubleAlgorithm(values);
   algo.run();
   return algo.getResult();
}

public class AbstractAlgorithm {
  public  run() {
     double sum = 0.0;
     for(int i=0; i<rows(); i++) {
       for(int j=0; j<columns(i); j++) {
          sum+=getElement(i, j);
       }
     }
     handleResult(sum);
  }
  protected abstract int rows();
  protected abstract int columns(int row);
  protected abstract double getElement(int i, int j);
  protected abstract void handleResult();
}

public class IntAlgorithm extends AbstractAlgorithm {
    int [][] values;
    int result;
    IntAlgorithm(int [][] values) {
       this.values= values;
    }
    public int rows() {
      return values.length;
    }
    public int columns(int row) {
      return values[row].length;
    }
    public double getElement(int i, int j) {
      return values[i][j];
    }
    public void handleResult(double result) {
      this.result = (int)result;
    }
    public int getResult() {
      return result;
    }
}

正如您所看到的,它相当冗长,但如果您的算法很大,这可能是值得的。希望您知道如何扩展到您的算法。

正如Thilo所指出的那样,仅将int / long视为double来处理所有算法并不安全,但对于数字而言,这已经足够好了。如果对您来说不够好,那么您需要更详细地工作,找出您需要的数字属性(例如添加)并将其提取到单独的接口中。对于中位数滤波器,我预计仅使用双精度浮点数就足够了,但我会测试边缘情况。


他可以将其作为Object[](具有一维)传递。 - Thilo
请问您能否提供第二部分建议的代码示例? - jayakumar
做完了。我甚至还没有编译它,但希望你能理解我的意思。 - Nick Fortescue
我不是很确定我是否想要在double中进行int[]和long[]的实际计算。 - Thilo
如果他想避免重复代码,他必须以双倍方式执行它们,除非他开始使用“可求和”接口或类似接口,这会使情况变得更加复杂。对于整数或长整数计算,将其作为双精度浮点数进行计算取决于算法,我认为在大多数情况下,对于中值滤波器来说这是可以的。 - Nick Fortescue

1

对于原始数组来说,没有一个好的方法来做到这一点,这就是为什么所有的库函数(如java.util.Arrays)也都有这些重复的方法。

你可以定义一个方法

Object[] medianfilter(Object[] arr); // note the missing dimension

使用反射来查找运行时类型。这就是System.arraycopy正在做的事情。但是你需要进行类型转换。很丑陋。

int[][]  result = (int[][]) medianFilter( input );

使用重复的方法。


删掉最后一句话,我讨厌那些重复的东西 :-) +1 - Sean Patrick Floyd
更好的做法是:不要编写重复的代码,而是编写一个可以为您执行此操作的脚本。理想情况下,您应该将其作为构建过程的一部分自动生成,但我猜这不是经常更改的代码,因此每次更改实现细节时手动运行脚本可能并不那么糟糕。 - gustafc
1
除非绝对必要,否则不要干扰您的构建过程。 - Thilo

1

有一种通用的方法可以传递数组的类型:

public T test(T[][] arg)
{
    T[][] q = arg;
    T[]   r = q[0];
    T     s = r[0];

    return s;
}

...不幸的是,它对于原始类型无效。您需要使用Integer和Float作为参数化类型。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接