Вопрос по java, arrays – Абстрагирование размерности массивов в Java

10

В Java массивы разных размерностей имеют разные типы. Так что метод, который принимаетint[] в качестве параметра не может бытьint[][] или жеint[][][], У меня есть много кода, где я создаю методы, которые очень похожи, но для размерности массива. Есть ли способ обработки массивов произвольной размерности и, таким образом, абстрагирование этой общей функциональности?

Не могли бы вы привести пример функциональности, которая не зависит от размерности массива? dasblinkenlight
@Glitch Генерация шума в 1D, 2D и 3D. Matthew Piziak
Что делает ваш код, что имеет смысл иметь разные размерные массивы? n00begon
Нет, пути нет. Louis Wasserman
@dasblinkenlight: сумма содержимого массива; обнулить массив; добавить два массива; в основном любая операция с массивом в целом. Вам нужно познакомиться с языком обработки массивов, таким как Fortran95 или (действительно весело!) APL. Ira Baxter

Ваш Ответ

6   ответов
0

что хотите, просто с помощью линейных массивов .... подумайте об этом

2

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

public void method ( int [] i ) {  //1-d array
    //logic 
}

public void method ( int [][] i) {  //2-d array
     for (int [] j : i) {
         method(j);
     }
}

public void method ( int [][][] i) {   // 3-d array
    for ( int [][] j : i ) {
        method(j);
    }
}

...так далее

0

нет". Как указывалось в других ответах, типы массивов с разными размерностями не совместимы с присваиванием. Однако возможен выход.

Типыint[] int[][] а такжеint[][][] все подтипыObject, И (например)int[][] на самом деле массивint[] экземпляров. Такfor some calculations может быть возможно сделать что-то вроде этого:

public void calc(Object array) {
    if (array instanceof int[]) {
        calc((int[]) array);
    } else if (array instanceof int[][]) {
        for (a int[] : (int[][]) array) {
            calc(a);
        }
    } else if (array instanceof int[][][]) {
        for (a int[][] : (int[][][]) array) {
            for (a2 int[] : a) {
                calc(a2);
            }
        }
    } else {
        throw new ClassCastException(...);  // or something more appropriate
    }
}

public void calc (int[] array) {
    // do the calculation
}

Предостережения:

this only works if the calculation works this way,

you have to repeat this ugly boilerplate for each method, and

the boilerplate could actually be worse than having three separate methods.

Теперь, в зависимости от расчета (и требований к производительности), вы сможете обобщить код, выполнив вычисление в объекте, который можно передать в обобщенный «применить ко всем элементам». Способ; например

public interface Calc {
    public void calc(int i);
}

... 

public void doCalc(Object array, Calc calculator) {
    // as above
}

public void doCalc(int[] array, Calc calculator) {
    for (int i : array) {
        calculator.calc(i);
    }
}

... но все еще много шаблонов ... и вы получите удар по производительности.

2

вы можете сделать это с помощью небольшой рекурсии (не удивительно, правда?) И размышлений.

Идея состоит в том, чтобы написать ваш метод так, чтобы он повторялся до тех пор, пока массив не будет иметь только одно измерение. Как только вы окажетесь на одномерном уровне, сделайте свою работу; в противном случае, называйте себя рекурсивно и объединяйте результаты предыдущих уровней, если это необходимо.

Вот быстрое демо:

import java.util.*;
import java.lang.*;
import java.lang.reflect.Array;

class Main {
    public static int sumArray(Object array) {
            Class type = array.getClass();
            if (!type.isArray()) {
                    throw new IllegalArgumentException("array");
            }
            Class ct = type.getComponentType();
            int res = 0;
            int len = Array.getLength(array);
            if (ct.isArray()) {
                    for (int i = 0 ; i != len ; i++) {
                            res += sumArray(Array.get(array, i));
                    }
            } else {
                    for (int i = 0 ; i != len ; i++) {
                            res += Array.getInt(array, i);
                    }
            }
            return res;
    }
    public static void main (String[] args) throws java.lang.Exception
    {
            int[] a = new int[] {1,2,3,4,5,6,7,8,9,10};
            int aa[][] = new int[][] {{1,2},{3,4},{5,6}};
            int aaa[][][] = new int[][][]{{{1,2},{3,4},{5,6}},{{7,8},{9,10},{11,12}}};
            System.out.println(sumArray(a));
            System.out.println(sumArray(aa));
            System.out.println(sumArray(aaa));
    }
}
0

скрыв его реализацию в классе (простите или исправьте мой синтаксис Java, я не кодер Java):

class MultidimensionalArray<Type> {

   // Implement N-dimensional 0-origin array of <Type>

   int[] dimensions;

   Type[] body;

   MultidimensionalArray(index1: int)
   {  dimensions=new int[1];
      dimensions[0]=index1;
      body=new Type[index1];
   }

   MultidimensionalArray(index1: int, index2: int)
   {  dimensions=new int[2];
      dimensions[0]=index1;
      dimensions[1]=index2;
      body=new Type[index1*index2];
   }

   MultidimensionalArray(int[] indexes)
   {  size=1;
      dimensions=indexes;
      for(int i=0;i<indexes.size();i++) size*=indexes[i];
      body=new Type[size];
   }

   Type Get(int index1) {
      assert dimensions.size()==1;
      return body[index1];
   }

   Type Get(int index1, int index2) {
      assert dimensions.size()==2;
      return body[index1*dimensions[0]+index2];
   }

   Type Get(int[] indexes) {
      int index=indexes[0];
      assert dimensions.size()==indexes.size();
      for (int i=0;i<indexes.size();i++) index=index*dimensions[i]+indexes[i+1];
      return body[index];
   }

   void Put(int index1, Type v) {
      assert dimensions.size()==1;
      body[index1]=v;
   }

   void Put(int index1, int index2, Type v) {
      assert dimensions.size()==2;
      body[index1*dimensions[0]+index2]=v;
   }

   void Put(int[] indexes, Type v) {
      int index=indexes[0];
      assert dimensions.size()==indexes.size();
      for (int i=0;i<indexes.size();i++) index=index*dimensions[i]+indexes[i+1];
      body[index]=v;
   }

}

Вы инициализируете это, вызывая его конструктор и получая доступ к элементу, передавая в массиве целых чисел в качестве набора индексов. Немного неуклюже, но работает:

int[] mydimensions={2,3,5};
MyArray MultidimensionalArray<int>=new MultidimensionalArray(mydimensions);
... 
int[] indexset={1,2,4};
MyArray.Put(indexset,22);
...
indexset = {0,1,3};
...  MyArray.Get(indexset) ...

Я добавил удобные функции для одномерных и двумерных массивов, которые не требуют наборов индексов, а скорее используют отдельные аргументы в качестве индексов. Легко обобщается на массивы измерения K. Вы также можете добавить функции для создания наборов индексов различных размеров.

Все это идет по цене некоторых накладных расходов.

Error: User Rate Limit Exceedednew Type[index1].
Error: User Rate Limit Exceeded
0

нет. Длинный ответ извините, но нет. Из-за того, как Java обрабатывает массивы, эти два принципиально разных типа, и на самом деле не существует какого-либо хорошего способа обрабатывать массивы любого измерения с помощью одного куска кода.

Похожие вопросы