【问题标题】:Java Generic Primitive type n-d arrayJava Generic Primitive 类型 a-n-d 数组
【发布时间】:2010-09-22 07:32:36
【问题描述】:

我必须将原始二维数组传递给过滤例程。过滤算法(中值过滤器)是相同的,与数组的类型无关。有没有办法以通用方式传递任何类型的数组或应该我用不同的数组类型重载了相同的函数。在第二种情况下,必须为不同的数据类型重复相同的代码。

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

有没有办法使上述代码成为通用代码,而不是在每个重载函数中重复中值滤波器的代码?

【问题讨论】:

    标签: java arrays generics


    【解决方案1】:

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

    你可以定义一个方法

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

    并使用反射找出运行时类型。这就是 System.arraycopy 正在做的事情。但是您随后需要进行类型转换。丑。

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

    使用重复的方法。

    【讨论】:

    • 刮掉最后一句话,我讨厌那些重复的 :-) +1
    • 更好的是:不要编写重复的代码,编写一个为您执行此操作的脚本。理想情况下,您会在构建过程中为您自动生成它,但我想这不是会经常更改的代码,因此每次更改实现细节时手动运行脚本可能不是太糟糕了。
    • 除非绝对必要,否则不要乱搞你的构建过程。
    【解决方案2】:

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

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

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

    【讨论】:

      【解决方案3】:

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

      为了避免算法中的代码重复(如果代码很多),您可以使用 double getElement(int i, int j)handleResult(double result) 等抽象方法生成一个名为 DoubleAlgorithm 之类的抽象类,然后编写非常小的子类this,每个原始类型一个。

      让我用一个例子来解释(假设算法是添加数字)。

      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 所指出的,仅将整数 / 长整数视为双精度数来执行所有算法并不安全,但对于一个数字来说,这已经足够了。如果它不适合您,那么您需要更加详细,找出您需要的数字属性(例如添加)并将它们提取到单独的界面。对于中值滤波器,我希望只使用双精度数就可以了,但我会测试边缘情况。

      【讨论】:

      • 他可以将它作为 Object[] 传入(一维)
      • 能否为您的建议的第二部分提供代码示例?
      • 完成。我什至没有编译这个,但希望你能明白
      • 不太确定我是否想对 int[] 和 long[] 进行双精度计算。
      • 如果他想避免重复代码,他必须双重执行,除非他开始使用“Summable”接口或类似的接口,否则会变得更加复杂。是否可以将 int 或 long 计算作为双精度计算取决于算法,我希望在大多数情况下,对于中值滤波器来说它会很好
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-01-02
      • 1970-01-01
      • 2020-02-24
      • 1970-01-01
      • 2019-03-29
      • 2018-10-21
      • 1970-01-01
      相关资源
      最近更新 更多