2010-09-22 2 views
3

Мне нужно передать примитивный 2d-массив в процедуру фильтрации. Алгоритм фильтрации (медианный фильтр) такой же, независимо от типа массива. Есть ли способ передать любой тип массива в общем случае, или я должен перегружать одну и ту же функцию с разными типами массивов. Во втором случае один и тот же код должен быть повторен для разных типов данных.Java Generic Primitive type nd array

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

Есть ли способ, чтобы сделать код выше общий один, вместо того чтобы повторять код медианный фильтр в каждый представляет собой каждый перегруженная функция?

ответ

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; 
    } 
} 

Как вы можете видеть, это довольно многословие, но если бы ваш алгоритм был большим, это могло бы стоить того. Надеюсь, это очевидно, как перейти к вашему алгоритму.

Как отметил Тило, небезопасно делать все алгоритмы, просто рассматривая ints/longs как парные, но для числа это будет достаточно хорошо. Если это не для вас, вам нужно сделать еще более подробный, выяснить, какие свойства нужных вам чисел (например, добавить) и извлечь их в отдельный интерфейс. Для медианного фильтра я ожидал бы, что использование удвоений будет работать нормально, но я бы проверил краевые случаи.

+0

Он может передать его как объект [] (с одним измерением) – Thilo

+0

Можете ли вы дать образец кода для второй части вашего предложения? – jayakumar

+0

сделано. Я даже не скомпилировал это, но, надеюсь, вы получите идею –

1

Не существует хорошего способа сделать это для примитивных массивов, поэтому все функции библиотеки (такие как java.util.Arrays) также имеют эти дублированные методы.

Вы можете определить метод

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

и использовать отражение, чтобы узнать тип выполнения. Это то, что делает System.arraycopy. Но тогда вам нужно вводить текст. Некрасиво.

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

Пойдите с дублированными методами.

+0

Поцарапать последнее предложение, я ненавижу эти дубликаты :-) +1 –

+0

Еще лучше: Дон 't пишите дублирующий код, напишите сценарий, который сделает это за вас. В идеале у вас есть автогенерация для вас как часть процесса сборки, но я думаю, что это не код, который будет меняться особенно часто, поэтому запуск скрипта вручную каждый раз, когда вы меняете детали реализации, вероятно, не является все это плохо. – gustafc

+1

Не связывайтесь с процессом сборки, если это абсолютно необходимо. – Thilo

1

Существует способ, чтобы передать тип массива в общем порядке:

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

    return s; 
} 

... к сожалению, это не будет работать для примитивных типов. Вам нужно будет использовать Integer и Float в качестве ваших параметризованных типов.