Java函数用于int[]、float[]或double[]数组。

6

我想编写一个Java函数,其输入可以是int[]float[]double[]。算法完全相同(一种标量积)。如何编写一个能够处理所有数字数组类型的单个函数?


你想在这个单一的函数中处理什么?你能举个例子吗? - Rakesh
7个回答

6

在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[],并始终使用doubles进行操作。最好创建重载版本的方法,其中只需要对int[]float[]进行转换,并委托给实际的double[]实现。

  • 我相信Scala可以无缝处理这个问题,因为在Scala中Java原始类型在语义上是对象。


很遗憾,您无法将两个数字相乘。 - aioobe
1
@aioobe: 嗯,我不能执行 number1 * number2,但我可以执行 number1.doubleValue() * number2.doubleValue()... - Tomasz Nurkiewicz

5

如果不是对每个情况分别编码,就需要使用反射来操作数组。但这很可能会使代码变得混乱、容易出错,并且比最优解慢一个数量级。在Java中,int[]float[]double[]唯一的共同超类型是Object,因此无法针对这些类型使用多态解决方案。 同样,泛型要求类型参数是引用类型,而intfloatdouble并不是引用类型。

你必须接受有重复代码的事实,或者更改数组的表示类型;例如,使用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.

如果您只处理相对较小的数组,那么通用但效率较低的解决方案可能已经足够快了。


1
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 for the solution,但它只适用于包装版本(仅限整数、浮点数和双精度数组),而我需要int、float和double数组。 - Erel Segal-Halevi

1

我看到有两种选择:

1)您可以创建一个新类,允许在构造函数中传入 int[]、float[] 和 double[],并将它们保存下来。

2)您允许传入 Object[],然后检查其中的元素是否为 int/float/double(您需要先进行转换)。


在Java中,您无法将int[](或float[]double[])作为Object[]传递。这些类型不兼容。 - Stephen C
是的,你必须先进行转换。 - Tobias

1

使用 java.lang.Number 类型或 Object 参数类型。

更多信息请阅读 有界类型参数


4
泛型对于基础类型为原始类型的数组没有帮助。 - Stephen C

0
希望这会对你有所帮助。我已经测试过了这段代码,它可以实现你所要求的功能,如何实现这个逻辑取决于你!
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

谢谢,但这不是我想要的 - 我想找到一种方法来对所有类型的数组执行相同的操作,而你的函数执行了不同的操作(除非我实现三次相同的操作)。 - Erel Segal-Halevi
Java不是魔法...所以在某个地方,你必须进行一些编码...如果你能稍微具体一点,说明想要完成什么相同的操作,那我可以帮助你解决! - Rakesh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接