Java-функция для массива int[], float[] или double[]

#java #arrays

#java #массивы

Вопрос:

Я хочу написать Java — функцию, которая будет получать в качестве входных данных либо int[] , float[] либо double[] . Алгоритм точно такой же (какое-то скалярное произведение). Как я могу написать единую функцию, которая сможет обрабатывать все типы числовых массивов?

Комментарии:

1. Что вы хотите обработать в этой единственной функции?? можете ли вы привести какой-нибудь пример?

Ответ №1:

В Java нет простого способа справиться с этим. Вы можете:

  • Используйте типы оболочек ( Integer[] , Float[] , Double[] ) и принимайте функцию Number[] в качестве аргумента. Работает, поскольку массивы ковариантны в Java:

 public static void main(String[] args) {
    f(new Integer[]{1,2,3});
    f(new Float[]{1,2,3});
    f(new Double[]{1,2,3});
}

private static void f(Number[] numbers) {
    f[0].doubleValue();
}
  

Обратите внимание, что этот подход значительно увеличивает потребление памяти.


  • Преобразуйте int[] массивы и float[] массивы в double[] двойники и работайте с ними постоянно. Предпочтительно создавать перегруженные версии вашего метода, в которых те, которые принимают int[] и float[] выполняют только преобразование и делегируют фактическую double[] реализацию.

  • Я считаю, что Scala может легко справиться с этим, поскольку примитивные типы Java семантически являются объектами в Scala.

Комментарии:

1. К сожалению, вы не можете умножить два числа.

2. @aioobe : ну, я не могу этого сделать number1 * number2 , но я могу number1.doubleValue() * number2.doubleValue()

Ответ №2:

Вы не можете закодировать это на Java без:

  • кодирование каждого случая отдельно или,

  • использование отражения для всех операций с массивом … что, вероятно, будет беспорядочным, хрупким и на порядок медленнее, чем оптимальное решение.

Единственным распространенным супертипом int[] float[] и double[] является Object , поэтому нет возможности решения с использованием полиморфизма по этим типам. Аналогично, общие термины требуют, чтобы параметр type был ссылочным типом, и int , float и double не являются ссылочными типами.

Вам нужно либо согласиться с тем, что у вас будет дублированный код, либо изменить тип представления для массивов; например, используйте Integer[] / Float[] / Double[] или Number[] .

Ответ №3:

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

 public static void main(String... args) throws IOException {
    int[] nums = new int[10*1000 * 1000];
    {
        long start = System.nanoTime();
        product2(nums);
        long time = System.nanoTime() - start;
        System.out.printf("Took %.3f seconds to take the product of %,d ints using an int[].%n", time / 1e9, nums.length);
    }
    {
        long start = System.nanoTime();
        product(nums);
        long time = System.nanoTime() - start;
        System.out.printf("Took %.3f seconds to take the product of %,d ints using reflections.%n", time / 1e9, nums.length);
    }
}

public static double product(Object array) {
    double product = 1;
    for (int i = 0, n = Array.getLength(array); i < n; i  )
        product *= ((Number) Array.get(array, i)).doubleValue();
    return product;
}

public static double product2(int... nums) {
    double product = 1;
    for (int i = 0, n = nums.length; i < n; i  )
        product *= nums[i];
    return product;
}
  

С принтами

 Took 0.016 seconds to take the product of 10,000,000 ints using an int[].
Took 0.849 seconds to take the product of 10,000,000 ints using reflections.
  

Если вы работаете только с относительно небольшими массивами, общее, но менее эффективное решение может быть достаточно быстрым.

Ответ №4:

Используйте java.lang.Number тип или Object тип параметра.

Для получения дополнительной информации прочитайте Параметры ограниченного типа

Комментарии:

1. Общие методы не помогут для массивов, базовый тип которых является примитивным типом.

Ответ №5:

Я вижу два варианта:

1) Вы можете создать новый класс, который разрешает int[], float[], double[] в конструкторе и сохраняет их.

2) Вы разрешаете Object[] и проверяете наличие int / float / double . (Сначала вы должны преобразовать их)

Комментарии:

1. Вы не можете передать int[] (или float[] или double[] ) как Object[] . Типы несовместимы в Java.

2. Да; вы должны преобразовать их раньше.

Ответ №6:

 class ArrayMath {
    private ArrayMath() {
    }

    public static <T extends Number> double ScalarProduct(T[] a, T[] b){
        double sum = 0;

        for(int i=0;i<a.length;  i){
            sum  = a[i].doubleValue()*b[i].doubleValue();
        }
        return sum;
    }
}
class Sample {
    public static void main(String arg[]){
        Integer[] v1 = { 1, -10, 3, 9, 7, 99, -25 };
        Integer[] v2 = { 1, -10, 3, 9, 7, 99, -25 };
        double p_int = ArrayMath.ScalarProduct(v1, v2);
        Double[] v1_d = { 1.1, -10.5, 3.7, 9.98, 7.4, 9.9, -2.5 };
        Double[] v2_d = { 1.1, -10.5, 3.7, 9.98, 7.4, 9.9, -2.5 };
        Double p_double = ArrayMath.ScalarProduct(v1_d, v2_d);

        System.out.println("p_int:"   p_int);
        System.out.println("p_double:"   p_double);
    }
}
  

Комментарии:

1. 1 для решения, однако, оно работает с коробочными версиями (только целочисленные, плавающие и двойные массивы), в то время как я хотел, чтобы массивы int, float и double .

Ответ №7:

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

 public class MultiDataType {

    public static void main(String[] args) {

        int[] i = new int[2];
        float[] f = new float[2];
        double[] d = new double[2];
        String str = new String();

        handlingFunction(i);
        handlingFunction(f);
        handlingFunction(d);
        handlingFunction(str);
    }

    public static void handlingFunction(Object o) {
        String classType = null;
        if (o.getClass().getCanonicalName().equals("int[]")) {
            classType = "int[]";// Your handling code goes here
        } else if (o.getClass().getCanonicalName().equals("float[]")) {
            classType = "float[]";// Your handling code goes here
        } else if (o.getClass().getCanonicalName().equals("double[]")) {
            classType = "double[]";// Your handling code goes here
        }else classType = o.getClass().getCanonicalName();

        System.out.println("Object belongs to "   classType);
    }

}
  

ВЫВОД

 Object belongs to int[]
Object belongs to float[]
Object belongs to double[]
Object belongs to java.lang.String
  

Комментарии:

1. Спасибо, но это не то, что я имел в виду — я хотел найти способ выполнять ОДНО и то же действие для всех типов массивов, в то время как ваша функция выполняет ДРУГОЕ действие (если я не выполняю одно и то же 3 раза).).

2. Java — это не волшебство … поэтому в том или ином месте вам нужно выполнить некоторое кодирование… если вы немного конкретизируете, какое действие вы хотите, я могу вам помочь!