Java Generic Primitive type n-d array
I have to pass a primitive 2d array to a filtering routine.The algorithm for filtering(median filter) is same irrespective of the type of the array.Is ther开发者_运维问答e a way to pass any type of array in a generic manner or should I overload the same same function with different array types.In the second case the same code will have to be repeated for different data types.
int[][] medianfilter(int[][] arr){ ... }
float[][] medianfilter(float[][] arr){ ... }
Is there a way to make the above code a generic one,instead of repeating the code for medianfilter in each an every overloaded function ?
There is no good way to do this for primitive arrays, which is why all the library functions (such as java.util.Arrays) also have these duplicated methods.
You could define a method
Object[] medianfilter(Object[] arr); // note the missing dimension
and use reflection to find out the runtime type. This is what System.arraycopy is doing. But you then need to type-cast. Ugly.
int[][] result = (int[][]) medianFilter( input );
Go with the duplicated methods.
There is a way to pass the type of an array in a generic manner:
public T test(T[][] arg)
{
T[][] q = arg;
T[] r = q[0];
T s = r[0];
return s;
}
... unfortunately it won't work for primitive types. You'll need to use Integer and Float as your parameterized types.
The only way to pass it in a generic manner and keep it as a primitive array is as an Object
. Personally, I'd just overload it, and see it as a cost of using primitives.
To avoid duplication of code in the algorithm (if it is a lot of code) you could produce an abstract class called something like DoubleAlgorithm
with abstract methods like double getElement(int i, int j)
and handleResult(double result)
and then write very small subclasses of this, one for each primitive type.
Let me explain with an example (suppose the algorithm was adding the numbers).
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;
}
}
As you can see, it is quite verbose, but if your algorithm was big it might be worth it. Hopefully it is obvious how to extend to your algorithm.
As Thilo has pointed out, it isn't safe to do all algorithms with just treating ints/longs as doubles, but for a number it will be good enough. If it isn't for you, then you need to go even more verbose, work out which properties of numbers you need (eg add) and extract those to a separate interface. For a median filter, I would expect just using doubles will work fine, but I'd test the edge cases.
精彩评论