我必须将原始的2d数组传递给过滤例程。无论数组的类型如何,过滤算法(中值过滤器)都是相同的。有没有办法以通用的方式传递任何类型的数组或应该我使用不同的数组类型重载相同的函数。在第二种情况下,必须针对不同的数据类型重复相同的代码。
int[][] medianfilter(int[][] arr){ ... }
float[][] medianfilter(float[][] arr){ ... }
有没有办法让上面的代码成为通用代码,而不是在每个重载函数中重复使用medianfilter的代码?
答案 0 :(得分: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作为双精度进行处理是不安全的,但是对于一个数字来说它就足够了。如果它不适合你,那么你需要更加详细,找出你需要的数字属性(例如添加)并将它们提取到一个单独的界面。对于中值滤波器,我希望只使用双精度工作正常,但我会测试边缘情况。
答案 1 :(得分:1)
对于原始数组没有好的方法,这就是为什么所有库函数(例如java.util.Arrays)也都有这些重复的方法。
您可以定义方法
Object[] medianfilter(Object[] arr); // note the missing dimension
并使用反射来找出运行时类型。这就是System.arraycopy正在做的事情。但是你需要进行类型转换。难看。
int[][] result = (int[][]) medianFilter( input );
使用重复的方法。
答案 2 :(得分:1)
有一种方法可以通用方式传递数组类型:
public T test(T[][] arg)
{
T[][] q = arg;
T[] r = q[0];
T s = r[0];
return s;
}
...遗憾的是它不适用于原始类型。您需要使用Integer和Float作为参数化类型。